■ 기본 커맨드 패턴
1. 커맨드 객체는 특정 객체에 대한 특정 작업 요청을 함께 캡슐화한다.
[그림] 커맨드 객체 구조
실제로, 요청을 처리하는 리시버(receiver)에 대한 참조와 Execute() 메소드를 가지고 있다. Execute()에서는 리시버의 메소드를 호출함으로써 필요에 따라서는 일련의 메소드를 복수해 호출해서 비즈니스 요청을 수행한다. 커맨드 객체를 호출하는 측에서는 단지 Execute() 메소드만 호출하면 된다. 그 커맨드가 구체적으로 Execute()를 어떻게 구현하는지는 알 필요가 없다.
2. 작업을 요청하는 쪽(리모콘)과 작업을 하는 쪽(TV, CD 플레이어)을 커맨드 객체를 통해서 분리할 수 있다.
3. 캡슐화시 매개변수를 써서 여러 가지 다른 요구사항을 집어넣을 수도 있다.
ConcreteCommand(매개변수);
4. 커맨드 패턴을 사용하면 요청 내역을 큐에 저장해서 스케쥴러, 작업큐같은 프로그램을 만들거나 또는 작업 내역을 스택성 로그로 기록해서 도중에 에러가 발생하면 롤백하는 구조의 프로그램을 만들 수도 있다. 이것을 좀더 정교하게 만들면 트랜잭션 시스템을 구현하는 것도 가능하다.
레퍼런스
Head First Design Patterns 스토리가 있는 패턴 학습법
-Oreilly, 한빛 미디어
■ 커맨드 패턴 변형
앞에서는 커맨드 객체가 리시버(Receiver)에 대한 참조와 그 리시버를 이용해서 요청을 구현해야 하는 Execute()가 있어야 한다. 이런 경우는 리시버에 대한 참조를 가지고 있어야 한다는 점에서 리시버와 커맨드 객체와의 커플링이 존재하게 된다. 이런 커플링을 없애기 위해서 때로는 리시버와 Execute() 대신에 단일 이벤트 멤버로 대신할 수 있다.
[그림] 커맨드 객체
1. One handler : 하나의 이벤트 핸들러에서 여러 UI 이벤트(메뉴, 툴바)를 핸들링할 수 있다.
2. the business logic for handling the command : 그 하나의 이벤트 핸들러에 해당 명령을 핸들링할 수 있는 비즈니스 로직을 중앙 관리할 수 있다.
■ 커맨드 패턴 구현의 핵심 요소
커맨드 관리자
- 애플리케이션에서 필요로 하는 모든 커맨드들의 중앙 저장소
- 애플리케이션이 커맨드 목록을 관리할 수 있는 컬렉션용 API를 제공.
레퍼런스
Command Management
--------------------------------------------------------------------------------------------------------
Command Pattern
메소드 호출을 캡슐화 하는 패턴이다. 메소드 호출을 캡슐화하면 계산 과정의 각 부분들을 결정화 시킬 수 있기 때문에 계산하는 코드를 호출한 객체에서는 어떤 식으로 일을 처리해야 하는 지에 대해서 전혀 신경 쓰지 않아도 된다.
1. Command Pattern의 정의
커맨드 패턴을 이용하면 요구 사항을 객체로 캡슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있다. 또한 요청한 내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업 취소 기능도 지원 가능하다,
2. Command Pattern의 특성
커맨드 패턴을 사용하면 어떤 작업을 요청한 쪽하고 그 작업을 처리한 쪽을 분리시킬 수 있다. 커맨드 객체는 특정 객체에 대한 특정 작업 요청을 캡슐화한다. 커맨드 객체는 일련의 행동을 특정 리시버하고 연결시킴으로써 요구 사항을 캡슐화한 것이다. 행동과 리시버를 한 rorrorc 집어넣고, excute()라는 메소드 하나만 외부에 공개하여 이 메소드 호출에 의해서 리시버에서 일련의 작업이 처리된다. 외부에서 볼 때는 어떤 객체가 리시버 역할을 하는지, 그 리시버로 실제로 어떤 일을 하는지 알 수 없다. Excute()메소드를 호출하면 요구 사항이 처리된다는 것만 알 수 있을 뿐이다. 커맨드를 확장해서 여러 개의 커맨드를 한꺼번에 호출할 수 있게 해주는 매크로 커맨드 패턴도 있다.
3. Command Pattern의 클래스 다이어그램
4. Command Pattern의 구성
A. 클라이언트는 ConcreteCommand를 생성하고 Receiver를 설정한다.
B. Invoker에는 명령이 들어있으며, execute()메소드를 호출함으로써 커맨드 객체에게 특정 작업을 수행해 달라는 요청을 하게 된다.
C. Command는 모든 커맨드 객체에서 구현해야 하는 인터페이스 이다. 모든 명령은 execute()메소드 호출을 통해서 수행되며, 이 메소드에서는 리시버에 특정 작업을 처리하라는 지시를 전달한다.
D. Execute() 메소드에서는 리시버에 있는 메소드를 호출하여 요청된 작업을 수행한다.
E. Receiver는 요구사항을 수행하기 위해 어떤 일을 처리해야 하는지 알고 있는 객체이다.
F. ConcreteCommand는 특정행동과 리시버 사이를 연결 해준다.
5. Command Pattern의 장단점
커맨드 패턴은 작업을 요청하는 객체와 실제 작업을 수행하는 객체를 분리시켜주므로 시스템의 결합도가 낮아질 수 있으며, 두 객체가 독립적으로 변경 가능한 장점을 가진다. 커맨드 및 그 하위 클래스는 기존 클래스와 무관하게 확장이 가능하며, 확장된 클래스들은 클라이언트의 별다른 수정 없이 사용이 가능하다. Macro Command처럼 커맨드패턴에 컴포지트 패턴을 복합해서 적용할 경우 복잡한 작업을 기본적인 작업들로 구조화시켜 다룰 수 있는 장점이 있다
----------------------------------------------------------------------------------------------------
Command.java |
public interface Command { |
실제 작업을 정의한 Receiver 객체입니다.
Light.java |
public class Light { } |
실제작업을 실행할 커맨드 클래스 ConcreteCommand 를 구현한다.
LightOnCommand.java |
public class LightOnCommand implements Command { // 생성자에서 이 커맨드 객체를 제어할 특정 정보를 전달합니다..그 객체는 light라는 인스턴스 변수에 저장되고 // execute() 메소드가 호출되면 light 객체가 바로 그 요청에 대한 리시버가 됩니다. public void execute() { } |
버튼이 하나 밖에 없는 리모콘을 만들어 보면. 다음과 같다.
SimpleRemoteControl.java |
public class SimpleRemoteControl {
// 슬롯을 가지고 제어할 명령을 설정하기 위한 메소드 |
자 이제 테스트클래스를 만들고 실행해보자.
RemoteControlTest.java |
public class RemoteControlTest { public static void main(String[] args) { //remote 변수가 인보커(invoker)역할을 합니다. //필요한 작업을 요청할 때 사용할 커맨드 객체를 인자로 전달 받는다.
//리시버 객체를 생성
//커맨드 객체를 생성합니다. 이때 리시버를 전달합니다. //커맨드 객체를 인보커한테 전달합니다.
} |
커맨드 객체는 일련의 행동을 특정 리시버하고 연결시킴으로써 요구사항을 캡슐화한다.
이렇게 하기 위해서 행동과 리시버를 한 객체에 집어 넣고, execute() 라는 메소드 하나만 외부에 공개하는 방법을 사용한다. 메소드 호출에 의해서 리시버에서 일련의 작업이 처리된다. 외부에서 볼때는 어떤 객체가 리시버 역할을 하는지 그 리시버에서 실제로 어떤 일을 하는지 알 수 없습니다. 다만 execute()메소드를 호출하면 요구사항이 처리 된다는 것만 알수 있다.
정리하자면
커맨드 패턴을 사용하면 요청하는 객체와 그 요청을 분리시킬수 있다.
이렇게 분리시키는 과정의 중심에는 커맨드객체가 있으며 이객체가 행동이 들어있는 리시버를 캡슐화 한다.
인보커에서는 요청을 할때는 커맨드 객체의 execute()메소드만 호출하면 된다.
execute() 메소드에서는 리시버에 있는 행동을 호출한다.
적용예
스트러츠1.0 에서 Action클래스의 execute 메소드가 있다.
정의
요청내역을 객체로 캡슐화하여 클라이언트를 서로 다른 요청에 따라 매개변수화 할 수 있습니다.
'Design Patterns' 카테고리의 다른 글
Singleton Pattern - 바로 알기(HeadFirst Design Patterns #5) (0) | 2009.12.23 |
---|---|
스트래티지 패턴 2 (Head First 파헤치기 ver.1) (0) | 2009.11.12 |
스트래티지 패턴(Strategy Pattern) (0) | 2009.11.12 |
Observer Pattern (0) | 2009.11.11 |
Singleton Pattern - (0) | 2009.11.11 |