-
디자인 패턴 (7) - 커맨드 패턴언어/디자인패턴 2023. 9. 12. 11:31
1. 커맨드 패턴이란?
- 실행될 기능을 캡슐화하여 여러 기능을 실행할 수 있는 재사용성이 높은 클래스 설계 패턴
- 이벤트가 발생했을 때 실행될 기능이 다양+변경 가능성이 있을때, 이벤트 발생 클래스 변경하지 않고 재사용
- 행위 패턴 중 하나이다.
- 실행할 기능 캡슐화하여 실행 요구 호출자(클라이언트)클래스와 실제 기능 수신자 클래스 의존성 제거
- 실행될 기능이 변경되어도 호출자 클래스에 어떠한 수정 없이 그대로 사용가능
1.1 커맨드 패턴의 구조
- Command : 실행될 기능에 대한 인터페이스
- ConcreteCommand: 실제 실행되는 기능 구현
- Invoker : 기능의 실행을 요청하는 호출자 클래스
- Receiver: ConcreteCommand에서 execute 메서드 구현시 필요한 클래스
즉, ConcreteCommand 기능 실행하기 위해 사용됨
* 클라이언트가 커맨드를 만든다 -> 인보커에 set커맨드한다 -> 인보커는 커맨드는 execute를 호출 ->
execute된 콘크리트 커맨드는 구성된 객체 메서드 호출
*일련의 행동을 특정 리시버와 연결하여 요청을 캡슐화 (객체를 서로 다른 요청에 따른 매개변수화)
2. 만능버튼 만들기 (예시1)
public class Lamp{ public void turnOn(){//램프켜짐} } //버튼을 누르면 램프의 불이 켜짐 public class Button{ //호출자 private Lamp lamp; public Button(Lamp la) {this.lamp = la;} public void pressed(){ la.trunOn(); } } public class Client{ public static void main(String[] args){ Lamp lamp = new Lamp(); Button lampButton = new Button(lamp); lampButton.pressed(); } }
- Button을 눌렀을 때 불이 켜지는 이벤트
2.1 문제점
1. 버튼을 눌렀을 때 다른 기능을 실행하는 경우
ex 버튼 눌렀을 때 알람이 시작되게 하려면?
public class Alarm{ public void start(){ //알람울림 } } public class Button{ private Alarm alarm; public Button(Alarm al){this.alarm = al;} public void pressed() {alarm.start();} }
- 새로운 기능이 추가되면, 기존 Button내용을 수정해야함
2. 버튼을 누르는 동작에 따라 다른 기능 실행해야하는 경우 (이게 포인트)
public class Button{ private Lamp lamp; private Alarm al; public Button() //램프와 알람을 생성자에서 받음 public void pressed(String mode){ //mode에따라 lamp에 불을 켜거나 알람을 울림 //새로운 기능이 추가되면, 버튼을 수정해야함 //따라서 OCP위배 } }
2.2 커맨드패턴 적용
- 기능-> 버튼 눌렀을 때 이벤트가 변화가능성이 있다 -> 캡슐화
- Button클래스의 pressed메서드 구체적 기능을 직접구현하지 않고, 캡슐화된 기능을 외부에서 제공받아서
위임하자!
- Button클래스는 Command 인터페이스를 구성하고 execute를 호출
- LampOnCommand는 램프 온되도록 execute를 구현
- AlarmStartCommand는 알람이 켜지도록 구성
> Command와 Button
public interface Command{ public void execute(); } public class Button{ private Command co; public Button(Command co) { setCommand(co); } public void setCommand(command newCommand){ this.co = newCommand; } public void pressed(){ co.execute(); } }
-Lamp와 LampOnCommand
public class Lamp{ public void turnOn(){//} } public class LampOnCommand implements Command{ private Lamp lamp; public LampOnCommand(Lamp la){ this.lamp=la; } public void execute(){ lamp.turnOn(); } }
- Client
public class Client{ public static void main(String[] args){ Lamp lamp = new Lamp(); Command lampOnCommand = new LampOnCOmmand(lamp); Button button1 = new Button(lampOnCommand); button1.pressed(); } }
*Invoker는 커맨드를 가지고 있고, 커맨드는 Receiver를 구성함
-> 커맨드를 호출하면, 커맨드가 콘크리트가 구성한 Receiver의 메서드를 호출
* 전략패턴은 보통 최상위 Abstract클래스가 전략인터페이스와 전략을 수정할 방법을 가지고 있고,
새로운 구체 클래스를 만든 후 전략을 수정함 (추상화된 놈이 초기 전략 가짐 -> 구체는 경우에 따라 수정)
* 커맨드 패턴은 특정 클래스에서 전략 인터페이스를 사용하는데, 구체 전략에 따라 전략과 관련된 클래스가 맵핑되는 느낌 이런차이 아닐까?
'언어 > 디자인패턴' 카테고리의 다른 글
전략 패턴 (Strategy) (0) 2024.05.26 디자인패턴 (8) - 어댑터 패턴 (0) 2023.09.12 디자인 패턴 (6) - 싱글톤 패턴 (0) 2023.09.11 디자인 패턴 (5) - 추상 팩토리 패턴 (0) 2023.09.11 디자인 패턴 (4) - 팩토리 패턴 (0) 2023.09.11