명령 패턴
요청(메소드의 실행)을 객체로 캡슐화해주며(has-a관계), 파라미터를 통해 다양한 요청을 처리(처리하는 명령의 동적 변경)할 수 있도록 해줌
-
다양한 요청을 큐에 유지할 수 있으며, 요청을 저장할 수 있고, 요청 취소(undo) 기능도 제공
-
연산 수행을 요청하는 객체와 그 요청을 실제 실행하는 객체의 연결을 느슨하게 해줌
명령패턴을 사용하지 않는 경우
- 클라이언트가 요청을 실행하기 위한 모든 정보를 유지해야 함
- 요청 로그를 유지하기 힘듦
- 다른 요청을 실행하기 위해서는 많은 수정이 필요
요청을 객체로 캡슐화 → 이를 통해 다양한 요청을 인자로 전달할 수 있고, 요청을 큐에 유지 가능.
실행한 요청을 보관하여 재생할 수 있고, 요청을 취소할 수 있도록 해줌
실행 순서
- 클라이언트가 command 객체 생성
- 클라이언ㅌ트가 호출자에 command 객체 저장
- 클라이언트가 호출자에게 명령을 실행하도록 요청
패턴의 참여자
- 명령 interface : 구체적 명령 객체를 위한 interface
- 구체적 명령 : 명령 처리자와 행동 연결, 처리자가 제공하는 메소드를 이용하여 실제 행동 실행
- 실행자(invoker) : 요청의 실행 요구 → 명령 객체 유지
- 처리자(receiver) : 요청을 수행하기 위해 해야 하는 기능이 구현되어 있는 객체. 어떤 종류의 객체도 처리자가 될 수 있음
- 클라이언트 : 구체적 명령 객체를 생성하고 처리자와 연결. 실행자에게 명령의 실행 요청
인자가 필요한 명령 패턴
일반적으로 명령패턴은 주로 인자를 사용하지 않음
- 방법1 : 명령객체를 생성할 때 필요한 인자까지 전달하여 생성
- 명령 객체는 실행할 때마다 동일한 인자를 이용하여 요청
- 방법2 : 별도 setParams와 같은 메소드를 정의하여 사용
- 방법3 : 명령객체의 execute 메소드가 인자를 받도록 해줌 → 다양한 명령을 추상화하는 것이 번거로움
관찰자 패턴 vs 명령 패턴
관찰자
- 처리자는 사건을 기다림
- 사건(관찰 대상)이 일어나면 처리자(관찰자) 자동 실행
- 여러 처리자가 한 사건을 기다릴 수 있음
- 사건이 발생하면 사건 정보 유지 객체를 처리자에 전달
명령
- 사건이 발생했을 때 무언가 실행해야함
- 어떤 것이든 실행 가능
- 실행할 수 있는것 변경 가능
- 처리자 → 명령 객체
장점
- command 객체를 여러 객체가 공유
- 실행 시간에 command와 receiver 변경 가능
- 새로운 command 만들기 쉬움
- 명령의 요청자와 처리자를 분리할 수 있음
- 여러 명령 객체를 조합하여 매크로 명령을 만들 수 있음
- 명령 실행 시점과 방법에 대한 엄격한 통제 가능
단점
- 작은 명령 클래스들이 많이 만들어질 수 있음
- 코드 자체가 복작해질 수 있음
Undo/Redo
단순 명령 객체의 저장으로는 다중 undo와 redo를 제공하기 어려울 수 잇음
- 다중 undo와 redo를 제공해야 하면 별도 Command 관리자를 만들어 처리하는 것이 효과적일 수 있음