커맨드 패턴(Command Pattern) ; 캡슐화
요구사항을 객체로 캡슐화할 수 있으며, 매개변수를 써서 여러 가지 다른 요구사항을 집어 넣을 수 있다.
이를 통해 요청 내역을 큐에 저장하거나, 로그를 기록할 수 있으며, 작업취소 기능도 지원 가능하다.
또한 각 커맨드는 캡슐화 되므로, 안에서 어떤 방식으로 구현되던 상관없이 리시버 객체는 커맨드를 호출하기만 하면,
각 커맨드는 각자의 지정되어 있는 동작을 수행한다.
책에서 나오는 예시 - 리모컨 API 개발
리모컨 API를 개발해야 하는데 요구사항은 다음과 같다.
- 리모컨에는 On / off 버튼이 있다. 여기에는 어떠한 전자기기에 대한 제어가 주어질 지 모른다.
- ex) 어떤 TV라도 이 리모컨으로 on/off 를 제어할 수 있어야 한다.
- on/off 할 수 있는 영역은 총 7개가 주어진다.
즉 만능 리모컨을 만들어야 하는 문제가 주어지는데, 가장 문제는 각 기기마다 on/off 에 대한 인터페이스가 제각각 이라는 것이다.
따라서 리모컨 API 에서는 제각각인 전자기기의 인터페이스를 하나로 통일할 필요가 있다.
커맨드 패턴을 활용한 해결
RemoteController 클래스
1 | // 인보커 객체 |
Command 인터페이스
1 | public interface Command { |
LightOffCommand
1 | public class LightOnCommand implements Command { |
NoCommand ; null 객체
1 | /** |
결론
Command 인터페이스 구현체는 자신이 하려고 하는 Action 을 캡슐화 하고,
클라이언트 측에선 인터페이스로 추상화 하여 한층 유연하게 Command를 사용할 수 있다.
생각해보자
Spring에서 Command 의 예시로는 PoolBase의 내부 클래스인 SynchronousExecutor.execute(Runnable command)
정도로 볼 수 있을 것 같다.
Spring 같은 고도화된 프레임워크 내에선 특정 디자인 패턴이 단독으로 쓰이는 경우는 거의 없고,
여러 디자인 패턴이 복합적으로 구현되어 있다.
또한, 최근에는 디자인 패턴을 더욱 더 추상화한 라이브러리등의 지원으로 고전적인 디자인 패턴이 적용된 구현체를 찾기가
매우매우 어렵다ㅠㅠ..
invoke와 command pattern
invoke ; 사전적 의미는 ‘들먹이다, 부르다, 불러오다’ 이다.
Method 클래스 내에 정의되어 있는 invoke(Object obj, Object... args)
를 호출하면,
특정 메소드명으로, 매개변수를 직접 주입하여 실행이 가능하다.
그렇다면, invoke()
메서드 같은 것도 Command 패턴의 일종이라 볼 수 있을까?
Thread 와 Runnable 인터페이스
일반적으로 Thread 를 사용하려면, Runnable 구현체를 직접 정의하고, 이를 Thread 객체 생성 시 넘겨주고,
thread.start(); 식으로 사용하곤 한다.
그렇다면, 일종의 Command Pattern 으로 볼 수도 있는 거 아닌가? 라는 생각도 들었다.
결론
사실 어떤 클래스와 그 설계가 커맨드 패턴이다 아니다는 중요한게 아니라고 생각한다.
다만, 커맨드 패턴이 변화하는 부분에 대해 캡슐화를 하고, 이를 사용하는 측면에서는 유연하게 사용할 수 있게 도와준다는 점에서
혹시 이런 측면에서 구현된 좋은 설계 구현체가 있나 살펴보는 것일 뿐..