Ch6. 커맨드 패턴 : 호출 캡슐화하기

커맨드 패턴을 쓰면 어떤 작업을 요청하는 쪽과 그 작업을 처리하는 쪽을 분리할 수 있다.

Untitled

커맨드패턴 다이어그램

커맨드 인터페이스 구현

커맨드 객체는 모두 같은 인터페이스를 구현해야한다.

public interface Command {
	public void execute();
}

세부 기능 커맨드 클래스 구현

public class LightOnCommand implements Command {
	Light light;

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

	public void execute() {
		light.on();
	}
}

커맨드 객체 사용하기

public class SimpleRemoteControl {
	Command slot;
	public SimpleRemoteControl() {}

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

커맨드 패턴

<aside> 💡 커맨드 패턴(Command Pattern)을 사용하면 요청 내역을 객체로 캡슐화해서 객체를 서로 다른 요청 내역에 따라 매개변수화 할 수 있다. 이러면 요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용할 수 있다.

</aside>

  • 커맨드 객체는 일련의 행동을 특정 리시버와 연결함으로써 요청을 캡슐화 한 것

  • 행동과 리시버를 한 객체에 넣고, execute()라는 메소드 하나만 외부에 공개

No Command 객체

  • 일종의 널 객체 (Null Object)

  • 널 객체는 딱히 리턴할 객체도 없고 클라이언트가 null을 처리하지 않게 하고 싶을 때 활용하면 좋다.

작업 취소 기능 추가하기

  • 마지막으로 실행된 명령을 기록하는 인스턴스 변수를 추가하고 사용자가 UNDO 버튼을 누르면 기록해 뒀던 커맨드 객체 레퍼런스로 undo() 메소드를 호출한다.

  • 작업취소 히스토리 기능은 전에 실행한 커맨드 자체를 스택에 넣는다. 사용자가 UNDO 버튼을 누를 때마다 인보커에서 스택 맨 위에 잇는 항목을 꺼내 undo() 메소드를 호출하도록 한다.

커맨드 패턴 활용하기

커맨드로 컴퓨테이션의 한 부분을 패키지도 묶어서 일급 객체 형태로 전달할 수도 있다. 그러면 클라이언트 애플리케이션에서 커맨드 객체를 생성한 뒤 오랜시간이 지나도 그 컴퓨테이션을 호출할 수 있다.

이 점을 활용해서 커맨드 패턴을 스케줄러나 스레드 풀, 작업 큐와 같은 다양한 작업에 적용할 수 있다.

핵심 정리

  • 커맨드 패턴을 사용하면 요청하는 객체와 요청을 수행하는 객체를 분리할 수 있다.

  • 이렇게 분리하는 과정의 중심에서는 커맨드 객체가 있으며, 이 객체가 행동이 들어있는 리시버를 캡슐화한다.

  • 인보커는 무언가 요청할 때 커맨드 객체의 execute() 메소드를 호출하면 된다. execute() 메소드는 리시버에 있는 행동을 호출한다.

  • 커맨드는 인보커를 매개변수화 할 수 있다. 실행 중에 동적으로 매개변수화를 설정할 수 있다.

  • execute() 메소드가 마지막으로 호출되기 전의 상태로 되돌리는 작업 취소 메소드를 구현하면 커맨드 패턴으로 작업 취소 기능을 구현할 수 있다.

  • 매크로 커맨드는 커맨드를 확장해서 여러 개의 커맨드를 한번에 호출할 수 있게 해 주는 가장 간편한 방법이다. 매크로 커맨드로도 어렵지 않게 작업 취소 기능을 구현할 수 있다.

  • 프로그래밍을 하다보면 요청을 스스로 처리하는 ‘스마트’커맨드 객체를 사용하는 경우도 종종 있다.

  • 커맨드 패턴을 활용해서 로그 및 트랜잭션 시스템을 구현할 수 있다.

Last updated