본문 바로가기
IT 개인 공부/디자인패턴

커맨드 패턴(Command Pattern)

by Libi 2021. 8. 13.
반응형

커맨드 패턴(Command Pattern)은 행위(Behavioral) 패턴 중 하나로써 요청을 객체의 형태로 캡슐화하여 재이용하거나 취소할 수 있도록 요청에 필요한 정보를 저장하거나 로그에 남기는 패턴이다.

요청에 사용되는 각종 명령어들을 추상 클래스와 구체 클래스로 분리하여 단순화한다.

요청을 객체화시키기 때문에 상태가 남게 되며 이는 나중에 작업을 취소, 로그 등에 활용할 수 있다.

 

커맨드 패턴의 구조는 다음과 같다.

 

 

  • Invoker : Client가 요청을 전달하는 매개체, 내부에서 적절한 Command에게 해당 요청을 처리하도록 위임
  • Receiver : 요청을 처리하기 위해 수행해야 하는 일을 가지는 객체
  • Command : 요청을 실행, 취소하는 기능을 가지는 인터페이스, Receiver에게 요청을 처리해달라고 Invoker의 명령을 전달
  • ConcreteCommand : Receiver가 처리해야 하는 일을 실제로 구현, Invoker에서 excute(), undo() 등 호출을 통해 요청이 오면 Receiver에게 전달

 


전등, 에어컨 On/Off 명령을 수행하는 리모컨을 커맨드 패턴을 적용하여 구현해보자.

먼저 Command 인터페이스이다. 간단하게 명령을 실행하는 excute() 메서드 하나를 가지도록 한다.

public interface Command {
	public void excute();
}

 

다음으로 Receiver이다. 전등, 에어컨을 On/Off 하는 기능을 가진다.

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

public class AirConditioner {

	public void on() {
		System.out.println("AirConditioner On");
	}
	
	public void off() {
		System.out.println("AirConditioner Off");
	}
}

다음으로 ConcreteCommand이다. 등록해놓은 전등, 에어컨의 On/Off 기능을 수행하도록 한다.

Command 인터페이스를 implements 하기 때문에 Invoker에서는 Command만 변경하고 excute()를 호출하면 그에 맞는 요청을 처리해 줄 수 있게 된다.

[ Light ]

public class LightOnCommand implements Command {

	private Light light;

	public LightOnCommand(Light light) {
		this.light = light;
	}

	@Override
	public void excute() {
		light.on();
	}
}

public class LightOffCommand implements Command {

	private Light light;
	
	public LightOffCommand(Light light) {
		this.light = light;
	}
	
	@Override
	public void excute() {
		light.off();
	}
}

[ AirConditioner ]

public class AirConditionerOnCommand implements Command {

	AirConditioner air;

	public AirConditionerOnCommand(AirConditioner air) {
		this.air = air;
	}

	@Override
	public void excute() {
		air.on();
	}
}

public class AirConditionerOffCommand implements Command {

	AirConditioner air;
	
	public AirConditionerOffCommand(AirConditioner air) {
		this.air = air;
	}
	
	@Override
	public void excute() {
		air.off();
	}
}

마지막으로 Invoker이다. 리모컨의 역할을 수행하며 해당 요청을 등록하고 수행해 주면 내부에서 해당 요청을 적절히 처리해 준다.

즉, 명령을 객체화시킴으로써 복잡하게 요청마다 처리하도록 구현해 줄 필요가 없다.

public class RemoteControl {
	
	private Command command;
	
	public void setCommand(Command command) {
		this.command = command;
	}
	
	public void doAction() {
		command.excute();
	}
}

Client에서 각 객체들을 생성하여 요청을 처리한 결과는 다음과 같다.

public class Client {

	public static void main(String[] args) {
		RemoteControl remoteControl = new RemoteControl();
		Light light = new Light();
		LightOnCommand lightOn = new LightOnCommand(light);
		LightOffCommand lightOff = new LightOffCommand(light);
		AirConditioner airConditioner = new AirConditioner();
		AirConditionerOnCommand airConOn = new AirConditionerOnCommand(airConditioner);
		AirConditionerOffCommand airCondOff = new AirConditionerOffCommand(airConditioner);
		
		remoteControl.setCommand(lightOn);
		remoteControl.doAction();
		remoteControl.setCommand(lightOff);
		remoteControl.doAction();
		remoteControl.setCommand(airConOn);
		remoteControl.doAction();
		remoteControl.setCommand(airCondOff);
		remoteControl.doAction();
	}
}

 

 

 

반응형

'IT 개인 공부 > 디자인패턴' 카테고리의 다른 글

프록시 패턴(Proxy Pattern)  (0) 2021.07.31
플라이웨이트 패턴(Flyweight Pattern)  (0) 2021.07.31
메멘토 패턴(Memento Pattern)  (0) 2021.07.29
상태 패턴(State Pattern)  (0) 2021.07.29
중재자 패턴(Mediator)  (1) 2021.07.29

댓글