커맨드 패턴은 이벤트가 발생했을 때 실행될 기능이 다양하면서도 변경이 필요한 경우에 이벤트를 발생시키는 클래스를 변경하지 않고 재사용하고자 할 때 유용하다.
버튼을 눌러 램프를 킨다는 상황을 가정으로 코드를 구현해보면
Button Class가 Lamp를 주입받아 버튼을 눌렀을 떄 lamp의 turnOn 함수가 실행되는 것을 확인할 수 있습니다.
public class Lamp {
public void turnOn() {
System.out.println("Lamp On");
}
}
public class Button {
private Lamp theLamp;
public Button(Lamp theLamp) {
this.theLamp = theLamp;
}
public void pressed() {
theLamp.turnOn();
}
}
public class Client {
public static void main(String[] args) {
Lamp lamp = new Lamp();
Button lampButton = new Button(lamp);
lampButton.pressed();
}
}
이 경우 버튼을 눌렀을 때 램프가 켜지는 것 대신 다른 행동을 하고 싶을 때 코드를 수정해야한다는 문제점이 있으며 OCP에 위배됩니다.
버튼을 누르는 동작에 따라 다른 기능을 실행하려면 기능이 실행되는 시점에 필요한 프로그램을 선택할 수 있어야 합니다.
public class Lamp {
public void turnOn() {
System.out.println("Lamp On");
}
}
public class Alarm {
public void start() {
System.out.println("Alarming...");
}
}
enum Mode { LAMP, ALARM }
public class Button {
private Lamp theLamp;
private Alarm theAlarm;
private Mode theMode;
public Button(Lamp theLamp, Alarm theAlarm) {
this.theLamp = theLamp;
this.theAlarm = theAlarm;
}
public void setMode(Mode mode) {
this.theMode = mode;
}
public void pressed() {
switch (theMode) {
case LAMP:
theLamp.turnOn();
break;
case ALARM:
theAlarm.start();
break;
}
}
}
public class Client {
public static void main(String[] args) {
Lamp lamp = new Lamp();
Alarm alarm = new Alarm();
Button button = new Button(lamp, alarm);
button.setMode(Mode.LAMP);
button.pressed();
button.setMode(Mode.ALARM);
button.pressed();
}
}
버튼 Class 내에서 Mode를 설정 함에 따라 버튼을 눌렀을 때 다른 결과값이 나올 수 있습니다.하지만 이 경우에 필요한 새로운 기능을 추가할 때마다 반복적으로 코드 수정이 필요할 것입니다. 즉 이것 역시 OCP에 위배된다고 볼 수 있습니다.
따라서 이런 부분을 해결하기 위해서 Command라는 Interface를 Button이 가지게 설정하고 Lamp와 Alarm를 작동시키는 Command들이 Comand Interface를 상속받도록 처리하면 해결할 수 있습니다.
public interface Command {
public abstract void execute();
}
public class Button {
private Command theCommand;
public Button(Command theCommand) {
setCommand(theCommand);
}
public void setCommand(Command newCommand) {
this.theCommand = newCommand;
}
public void pressed() {
theCommand.execute();
}
}
public class Lamp {
public void turnOn() {
System.out.println("Lamp On");
}
}
public class LampOnCommand implements Command {
private Lamp theLamp;
public LampOnCommand(Lamp theLamp) {
this.theLamp = theLamp;
}
public void execute() {
theLamp.turnOn();
}
}
public class Alarm {
public void start() {
System.out.println("Alarming...");
}
}
public class AlarmOnCommand implements Command {
private Alarm theAlarm;
public AlarmOnCommand(Alarm theAlarm) {
this.theAlarm = theAlarm;
}
public void execute() {
theAlarm.start();
}
}
public class Client {
public static void main(String[] args) {
Lamp lamp = new Lamp();
Command lampOnCommand = new LampOnCommand(lamp);
Button lampButton = new Button(lampOnCommand);
lampButton.pressed();
Alarm alarm = new Alarm();
Command alarmOnCommand = new AlarmOnCommand(alarm);
Button alarmButton = new Button(alarmOnCommand);
alarmButton.pressed();
}
}
여기서 기능을 추가하고 싶다면 어떻게 접근해야할까?
public class Lamp {
public void turnOn() {
System.out.println("Lamp On");
}
public void turnOff() {
System.out.println("Lamp Off");
}
}
public class LampOnCommand implements Command {
private Lamp theLamp;
public LampOnCommand(Lamp theLamp) {
this.theLamp = theLamp;
}
public void execute() {
theLamp.turnOn();
}
}
public class LampOffCommand implements Command {
private Lamp theLamp;
public LampOnCommand(Lamp theLamp) {
this.theLamp = theLamp;
}
public void execute() {
theLamp.turnOff();
}
}
public class Client {
public static void main(String[] args) {
Lamp lamp = new Lamp();
Command lampOnCommand = new LampOnCommand(lamp);
Command lampOffCommand = new LampOffCommand(lamp);
Button lampButton = new Button(lampOnCommand);
lampButton.pressed();
lampButton.setCommand(lampOffCommand);
lampButton.pressed();
}
}
Lamp 객체 안에 turnOff() 함수를 만들고 Off에 해당하는 커맨드를 새롭게 생성해주면 됩니다.
반응형
'CS' 카테고리의 다른 글
데커레이터 (Decorator Pattern) 패턴 (0) | 2022.08.08 |
---|---|
옵저버 패턴 (Observer Pattern) (0) | 2022.08.02 |
스테이트 패턴 (0) | 2022.07.22 |
싱글톤 패턴 (Singleton Pattern) (0) | 2022.07.18 |
스트래티지 패턴 (Strategy Pattern) (0) | 2022.07.06 |
댓글