본문 바로가기

Design-Pattern

지금 부터 내가 명령한다! 커맨드 패턴(command pattern)

1. 커맨드 패턴(command pattern) 이란?

command(커맨드)는 명령이라는 뜻을 가지고 있죠 명령은 일의 지시 즉 요구사항의 전달을 의미합니다.

이를 기반으로 커맨드 패턴이 어떤 패턴인지 정리해 보면

커맨드 패턴은 요구 사항을 객체로 캡슐화할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수 있는 패턴입니다.

 

커맨드 패턴을 UML 다이어 그램으로 표현하면 다음과 같습니다.

커맨드 패턴 UML

2.  커맨드 패턴(command pattern)의 특징

커맨드 패턴은 실행될 기능을 캡슐화 함으로써 여러 가지 실행하는 재사용성이 높을 경우 쓰기 좋은 패턴입니다.

 

커맨드 패턴의 요소는 다음과 같습니다.

 

1. Invoker(발신자) : 커맨드를 저장하는 객체

2. Receiver(수신자) : 기능을 수행하는 객체

3. Command(커맨드) : 요청을 캡슐화하는 객체(행동 + Receiver 정보)

4. Client(클라이언트) : 커맨드 객체를 만들고, 행동을 결정

 

클라이언트에서 커맨드 객체 생성 -> 발신자로 커맨드 객체를 저장 -> 클라이언트에서 발신자를 통해 행동 요청을 전송 -> 수신자가 실행

 

과 같은 순서로 동작합니다.

 

커맨드 패턴의 장점은 다음과 같습니다.

1. 각각의 기능들이 캡슐화되어 있기에 결합도가 낮아집니다.

2. 클라이언트와 발신자 클래스 간의 의존성이 없어집니다.

3. 캡슐화를 통해 재사용성이 좋아집니다.

 

하지만 커맨드 패턴은 다음과 같은 단점도 있습니다

 

1. 클래스의 개수가 많아진다 

2. 클래스 개수의 증가는 곧 구조가 복잡해지고 파악이 어려워진다

 

등이 있습니다.

 

3.  커맨드 패턴(command pattern)의 구현

Command

public interface Command {
	public void execute();
}

GarageDoor

public class GarageDoor {
	public GarageDoor() { }
	public void up() { System.out.println("Garage Door is Open"); }
	public void down() { System.out.println("Garage Door is Closed"); }
	public void stop() { System.out.println("Garage Door is Stopped"); }
	public void lightOn() { System.out.println("Garage light is on"); }
	public void lightOff() { System.out.println("Garage light is off"); }
}

GarageDoorOpenCommand

public class GarageDoorOpenCommand implements Command {
	GarageDoor garageDoor;
	public GarageDoorOpenCommand(GarageDoor garageDoor) {
		this.garageDoor = garageDoor;
	}
	public void execute() { garageDoor.up(); }
}

Light

public class Light {
	public Light() {}
	public void on() { System.out.println("Light is on"); }
	public void off() { System.out.println("Light is off"); }
}

LightOffCommand

public class LightOffCommand implements Command {
	Light light;
	public LightOffCommand(Light light) { this.light = light; }
	public void execute() { light.off(); }
}

LightOnCommand

public class LightOnCommand implements Command {
	Light light;
	public LightOnCommand(Light light) { this.light = light; } 
	public void execute() { light.on(); }
}

RemoteControlTest

public class RemoteControlTest {
	public static void main(String[] args) {
		SimpleRemoteControl remote = new SimpleRemoteControl();
		Light light = new Light();
		GarageDoor garageDoor = new GarageDoor();
		LightOnCommand lightOn = new LightOnCommand(light);
		GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
		remote.setCommand(lightOn);
		remote.buttonWasPressed();
		remote.setCommand(garageOpen);
		remote.buttonWasPressed();
    }
}

SilpleRemoteControl

 

public class SimpleRemoteControl {
	Command slot;
	public SimpleRemoteControl() {}
	public void setCommand(Command command) { slot = command; }
	public void buttonWasPressed() { slot.execute(); }
}