커맨드(Command) 패턴
디자인 패턴 ·커맨드 패턴은 요청을 객체로 캡슐화하여 매개변수화하고, 이력을 관리하며, 작업을 지연하거나 취소할 수 있도록 하는 디자인 패턴입니다. 이 패턴을 사용하면 요청을 보내는 객체와 이를 수신하는 객체를 분리할 수 있어 유연성과 확장성이 증가합니다.
구성 요소
- 커맨드(Command): 실행될 명령어를 캡슐화하는 객체입니다.
- 수신자(Receiver): 커맨드 객체가 호출할 기능을 포함하는 객체입니다.
- 호출자(Invoker): 커맨드 객체를 저장하고, 수신자에게 명령을 전달하는 객체입니다.
- 클라이언트(Client): 호출자 객체를 생성하고 커맨드 객체를 생성하여 호출자 객체에 전달합니다.
구현:
- Command 인터페이스를 생성합니다.
- 각 명령어에 해당하는 ConcreteCommand 클래스를 생성합니다.
- Receiver 클래스를 생성합니다.
- Invoker 클래스를 생성합니다.
- Client 클래스를 생성하여 Invoker 객체를 생성하고, ConcreteCommand 객체를 생성한 후 Invoker 객체에 전달합니다.
장점
- 명령어의 실행을 쉽게 취소하거나 다시 실행할 수 있습니다.
- 호출자와 수신자 사이의 결합도를 낮출 수 있습니다.
- 새로운 명령어를 쉽게 추가할 수 있습니다.
단점
- 클래스의 수가 많아질 수 있습니다.
- 실행될 명령이 많아질 수록 복잡해질 수 있습니다.
예시
전등을 끄는 명령, 전등을 키는 명령 두개와 명령을 취소할 수 있는 버튼이 있다.
Command
public interface Command {
void execute();
void undo();
}
ConcreteCommand
public class LightOnCommand implements Command {
private final Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
this.light.on();
}
@Override
public void undo() {
if(this.light.isOn()){
this.light.off();
}else{
this.light.on();
}
}
}
Receiver
public class Light {
private boolean isOn;
public void on() {
System.out.println("불을 켭니다.");
this.isOn = true;
}
public void off() {
System.out.println("불을 끕니다.");
this.isOn = false;
}
public boolean isOn() {
return this.isOn;
}
}
Invoker
public class Button {
private final Stack<Command> commandStack;
public Button() {
this.commandStack = new Stack<>();
}
public void press(Command command) {
command.execute();
this.commandStack.push(command);
}
public void undo() {
if(this.commandStack.empty()){
return;
}
this.commandStack.pop().undo();
}
}
Client
class ButtonTest {
@Test
public void button_test(){
Button button = new Button();
button.press(new LightOnCommand(new Light()));
button.press(new LightOnCommand(new Light()));
button.undo();
button.undo();
}
}
결론
커맨드 패턴은 객체 지향 디자인 패턴 중 하나로, 실행될 명령어를 캡슐화하여 호출자와 수신자의 결합도를 낮추는 장점이 있습니다. 이 패턴은 텍스트 에디터, 게임, 리모컨 등에서 사용될 수 있으며, 명령어의 실행 취소와 재실행이 가능하다는 점에서 유용합니다.
예제는 이곳 에서 확인하실수 있습니다.