다른 방식의 캡슐화를 할 예정이다. 메소드 호출 자체를 캡슐화할 것이다.
Command Pattern은 요청을 객체로 캡슐화하는 것이다.
이를 통해 다른 객체를 다양한 요청으로 매개변수화할 수 있으며, 요청을 큐에 저장하거나 로그로 남기고, 실행 취소 작업을 지원할 수 있다.
Command Pattern은 다음 예시와 비슷하게 동작한다.
1. 손님이 점원에게 주문을 넘긴다. (createOrder)
2. 점원은 주문을 받고 주방에 넘겨 명령한다. (takeOrder)
3. 요리사는 주문대로 요리를 진행한다. (makeBurger... / output)
Command 인터페이스는 execute 메소드를 가진다.
각 영역의 command(LightOnCommand 같은)는 자신이 명령을 내릴 변수(Light 같은)를 가지며, 생성자에서 이를 주입받는다.
execute 메소드에서 자신이 행할 명령들을 수행한다.
각 remoteControl 에서는 Command 변수를 가지며, 이를 setCommand를 이용하여 변경하고,
buttonWasPressed 메소드를 실행하면 가지고 있는 command 변수의 execute 메소드가 실행된다.
RemoteControl 클래스는 onCommands 리스트와 offCommands 리스트를 변수로 가진다.
해당 클래스가 생성될 때, onCommands와 offCommands를 정의하며, 각 슬롯을 noCommand로 설정한다.
(noCommand의 execute를 빈 함수로 정의하여 별도로 설정되지 않은 슬롯 번호의 command를 실행했을 때 에러가 발생하지 않는다.)
setCommand에 슬롯 번호와, onCommand, offCommand를 입력하면 해당 번호에 맞게 onCommand와 offCommand가 리스트에 할당된다.
onButtonWasPushed에 슬롯 번호를 입력하면 해당 번호에 맞는 onCommand의 execute 메소드가 실행된다
offButtonWasPushed도 같은 원리로 동작한다.
각 커맨드의 undo() 메소드를 해당 커맨드의 실행과 반대되는 메소드로 정의한다.(예를 들어, LightOnCommand는 light.off 메소드)
RemoteControl 클래스에 undoCommand 변수를 정의하고, 어떠한 버튼이 눌렸을 때, 해당 커맨드를 undoCommand로 설정한다.
undoButtonWasPushed 메소드가 실행되면 undoCommand의 undo 메소드가 실행되며,
이전에 실행했던 커맨드의 undo 메소드가 실행되어, 해당 커맨드와 반대되는 메소드가 실행된다.(on <-> off)
public interface Command {
public void execute();
public void undo();
}
public class Light {
String location;
public Light(String location) {
this.location = location;
}
public void on() {
System.out.println(location + " Light On");
}
public void off() {
System.out.println(location + " Light Off");
}
}
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
public class Stereo {
String location;
public Stereo(String location) {
this.location = location;
}
public void on() {
System.out.println(location + " Stereo On");
}
public void off() {
System.out.println(location + " Stereo Off");
}
public void setCD() {
System.out.println(location + " Stereo Set CD");
}
public void setVolume(int volume) {
System.out.println(location + " Stereo Volume = " + volume);
}
}
public class StereoOnWithCDCommand implements Command {
Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
stereo.on();
stereo.setCD();
stereo.setVolume(11);
}
@Override
public void undo() {
stereo.off();
}
}
public class StereoOffWithCDCommand implements Command {
Stereo stereo;
public StereoOffWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
stereo.off();
}
@Override
public void undo() {
stereo.on();
stereo.setCD();
stereo.setVolume(11);
}
}
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteControl() {
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
undoCommand = noCommand;
for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPushed() {
undoCommand.undo();
}
}
public class CommandSimulation {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Light livingRoomLight = new Light("Living Room");
Light kitchenLight = new Light("Kitchen");
Stereo livingRoomStereo = new Stereo("Living Room");
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
StereoOnWithCDCommand stereoOn = new StereoOnWithCDCommand(livingRoomStereo);
StereoOffWithCDCommand stereoOff = new StereoOffWithCDCommand(livingRoomStereo);
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
remoteControl.setCommand(2, stereoOn, stereoOff);
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(2);
remoteControl.onButtonWasPushed(0);
remoteControl.undoButtonWasPushed();
}
}

'공부 > 디자인 패턴' 카테고리의 다른 글
| 8. Template Method Pattern (Head First Design Patterns) (1) | 2024.10.27 |
|---|---|
| 7-1. Adapter Pattern (Head First Design Pattern) (0) | 2024.10.25 |
| 5. Singleton Pattern (Head First Design Patterns) (0) | 2024.10.22 |
| 4. Factory Pattern (Head First Design Patterns) (0) | 2024.10.22 |
| 3. Decorator Pattern (Head First Design Patterns) (0) | 2024.10.20 |