-
[디자인패턴] 커맨드패턴기타/북스터디 2022. 12. 25. 08:30
1. 커맨드패턴(Command Pattern)이란?
커맨드패턴이란 요청을 캡슐화하여 호출자(invoker)와 수신자(receiver)를 분리하는 패턴이다.
요청 자체를 커맨드에 캡슐화하는 것으로 커맨드 안에서는 reeciver는 누구인지, receiver는 어떠한 일을 해야하는지 등 요청을 수행하기 위한 모든 작업을 내제하고 있는 것이다.
호출자(invoker)는 캡슐화된 커맨드를 가지고 있어 execute()라는 매서드를 호출만 하면 되는 구조이다.
커맨드패턴을 사용함으로서 요청을 객체로 캡슐화해서 객체를 서로 다른 요청에 따라 매개변수화할 수 있다.
또한, 호출자(invoker)입장에서는 받은 요청이 어떠한 과정으로 처리되는지 전혀 신경을 쓸 필요가 없어진다.
2. 커맨드패턴이 필요한 상황은 언제일까?
아래의 코드는 버튼을 누르면 불이 켜지는 상황을 가정한 코드이다.
public class Button { private Light light; public Button(Light light) { this.light = light; } public void press() { light.on(); } } public class Client { public static void main(String[] args) { Button button = new Button(new Light()); button.press(); } }
위 코드는 어떠한 상황에서 문제일까?
1. 버튼의 역할이 불을 키는 것이 아닌 끄는 역할을 해야한다면 Button 클래스의 press메서드 구현을 바꿔야한다.
2. 수신자(receiver)의 코드, 즉 Light쪽 코드가 바뀌면 호출자(invoker)의 코드가 바뀌어야한다.
3. 버튼의 역할이 불을 키고 끄는 것이 아닌 커튼을 치거나 걷는 역할을 한다면 호출자(invoker)의 내부구현은 모두 바뀌어야한다.
결국, 문제의 원인은 invoker와 receiver간의 강한 결합이다.
이 문제를 해결하는 방법으로 커맨드패턴을 사용하는 것이다.
3. 커맨드패턴을 적용해보자
먼저, 세부적인커맨드가 구현해야할 커맨드 인터페이스를 만들어주자.
(반드시 인터페이스일 필요는 없고 추상클래스로 만들어도 무방하다.)
public interface Command { void execute(); }
이렇게 메서드를 호출했을 때에 어떠한 일을 단순히 수행하는 추상메서드만 가진 인터페이스는 java에서 Runnable이라는 인터페이스가 존재하여 execute메서드 하나만 필요한 Command를 사용할 경우에는 Runnable을 이용하는 것도 방법이다.
https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html
이제 불을 켜는 커맨드를 구현해보자.
public class LightOnCommand implements Command { Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } }
이렇게 요청을 처리하는 세부적인 커맨드를 하나씩 만들어 주면 된다.
이렇게 커맨드를 구현하면 호출자(invoker)인 Button클래스와 클라이언트 코드는 아래와 같이 된다.
public class Button { private Command command; public Button(Command command) { this.command = command; } public void press() { command.execute(); } } public class Client { public static void main(String[] args) { Button button = new Button(new LightOnCommand(new Light()); button.press(); } }
커맨드패턴을 적용함으로서, 버튼이 해야할 역할이 바뀐다고해서 invoker의 코드를 수정할 필요가 없어졌고 단순히 클라이언트에서 Button생성자 호출코드에서 원하는 커맨드만 파라미터로 넣어주면 된다.
3. 커맨드패턴의 장점과 단점은 무엇일까?
- 장점
1. 기존 코드를 변경하지 않고 새로운 커맨드를 만들 수 있다.
2. 수신자의 코드가 변경되어도 호출자의 코드는 변경되지 않는다.
3. 커맨드 객체를 로깅, 큐 방식, 취소기능 등 다양한 방법으로 활용할 수 있다.
- 단점
1. 코드가 복잡하고 클래스가 많아진다.
<참고 자료>
1. 코딩으로 학습하는 GoF의 디자인 패턴(인프런강의, 백기선님)
2. 헤드퍼스트 디자인 패턴 개정판
'기타 > 북스터디' 카테고리의 다른 글
[디자인패턴] 프록시패턴 (0) 2023.01.08 [이펙티브 자바] 아이템12. toString을 항상 재정의하라 (0) 2023.01.02 [이펙티브 자바] 아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) 2022.12.12 [디자인패턴] 데코레이터 패턴 (0) 2022.12.11 [디자인패턴] 전략 패턴 (0) 2022.07.10