커맨드 패턴: 실행될 기능을 캡슐화하는 패턴
(실행될 기능을 캡슐화하여 이벤트를 발생시키는 클래스를 변경하지 않고 코드의 재사용성을 높이는 패턴)
기존 코드: 버튼을 누르면 Lamp가 켜지는 기능을 수행하는 코드
class Lamp{ public void turnOn() { System.out.println("Lamp On"); } } 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(); } }
문제점: 버튼을 누르면 다른 기능이 실행되는 경우, 버튼을 누르는 동작에 따라 다른 기능이 실행되는 경우에는 무조건 Button클래스를 수정해야 됨 -> OCP 위배
해결 방법: 구체적인 기능(실행될 기능)은 외부로부터 제공받아 캡슐화하여 Pressed 메소드에서 호출하는 방식으로 수정한다.
기존에는 Pressed 메소드가 Lamp 객체의 메소드를 호출하였지만, 이제는 Command 인터페이스를 구현한 객체의 메소드를 호출한다.
interface Command{ public abstract void execute(); } class Button{ private Command theCommand; public Button(Command theCommand) { setCommand(theCommand); } public void setCommand(Command newCommand) { this.theCommand=newCommand; } public void pressed() { // 버튼이 눌리면 주어진 Command의 execute 메서드롤 호출함 theCommand.execute(); } } class Lamp{ public void turnOn() { System.out.println("Lamp On"); } } class LampOnCommand implements Command{ // 램프를 켜는 클래스 private Lamp theLamp; public LampOnCommand(Lamp theLamp) { this.theLamp=theLamp; } public void execute() { theLamp.turnOn(); } } class Alarm{ public void start() { System.out.println("Alarming..."); } } 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 button1=new Button(lampOnCommand); // 램프를 켜는 커맨드를 설정함 button1.pressed(); // 버튼이 눌리면 램프 켜는 기능이 실행됨 Alarm alarm=new Alarm(); Command alarmOnCommand=new AlarmOnCommand(alarm); Button button2=new Button(alarmOnCommand); // 알람을 울리는 커맨드를 설정함 button2.pressed(); // 버튼이 눌리면 알람을 울리는 기능이 실행됨 button2.setCommand(lampOnCommand); button2.pressed(); // 이제 버튼이 눌리면 램프를 켜는 기능이 실행됨 } }
커맨드 패턴의 컬레보레이션
Command: 실행될 기능에 대한 인터페이스, 실행될 기능을 execute 메소드로 선언함
ConcreteCommand: 실제로 실행되는 기능을 구현, Command 인터페이스를 구현함
Invoker: 기능의 실행을 요청하는 호출자 클래스
Receiver: ConcreteCommand의 기능을 실행하기 위해 사용하는 수신자 클래스