디자인 패턴 – 커맨드 패턴

커맨드 패턴: 실행될 기능을 캡슐화하는 패턴
(실행될 기능을 캡슐화하여 이벤트를 발생시키는 클래스를 변경하지 않고 코드의 재사용성을 높이는 패턴)

기존 코드: 버튼을 누르면 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의 기능을 실행하기 위해 사용하는 수신자 클래스

Leave a Reply

Your email address will not be published. Required fields are marked *