커맨드 패턴: 실행될 기능을 캡슐화하는 패턴
(실행될 기능을 캡슐화하여 이벤트를 발생시키는 클래스를 변경하지 않고 코드의 재사용성을 높이는 패턴)
기존 코드: 버튼을 누르면 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의 기능을 실행하기 위해 사용하는 수신자 클래스