요청 자체를 객체로 만들어 실행될 기능을 캡슐화해 연산을 요청하는 객체와 수행하는 객체를 분리시켜 결합도를 낮추는 패턴이다.
1. 전등을 나타내는 Light 클래스가 있다 하자.
public class Light {
public void on() {
System.out.println("Light On");
}
public void off() {
System.out.println("Light Off");
}
}
2. Light를 키고 끄기위한 Client는 다음과 같다.
public class Client {
public static void main(String[] args) {
Light light = new Light();
light.on();
light.off();
}
}
위 상황에서 Client는 Light의 on, off를 직접 호출한다. 이런 경우는 Client와 Light간의 강한 결합이 발생되어 Light의 새로운 기능이나 기능변경이 이뤄질 때 Client의 코드를 수정해야 할수도 있다.
실행될 기능(Command)을 캡슐화해 Client와 Light사이의 의존성을 제거하자
1. Command
public interface Command {
void execute();
}
구조의 Command에 해당하는 인터페이스로 execute를 정의한다.
2. LightOn, LightOff Command
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
ConcreteCommand에 해당하는 클래스로 Receiver에 해당하는 Light에 명령(on,off)를 수행하도록 하는 클래스이다.
3. Light
public class Light {
public void on() {
System.out.println("The light is on");
}
public void off() {
System.out.println("The light is off");
}
}
Receiver에 해당하는 클래스로 실제 on, off 기능을 수행한다.
4. RemoteControl
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
Invoker에 하는 RemoteControl이다. 설정된 pressButton으로 Command에 기능을 요청한다.
5. Client
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl control = new RemoteControl();
control.setCommand(lightOn);
control.pressButton();
control.setCommand(lightOff);
control.pressButton();
}
}
커맨드 패턴이 적용된 Client로 Light가 변경거나 새로운 기능이 추가되어도 Client가 받는 영향이 적다. 즉, 기존의 코드 변경없이 command가 추가가능하다.
MacroCommand는 여러개의 커맨드를 한번에 실행할 수 있도록 하는 Command로 Command를 상속받으며 Command의 List를 가지고 있다.
public class MacroCommand implements Command {
private List<Command> commands;
public MacroCommand(List<Command> commands) {
this.commands = commands;
}
@Override
public void execute() {
for (Command command : commands) {
command.execute();
}
}
}