커맨드 패턴
요청을 캡슐화하여 호출자(invoker)와수신자(receiver)를 분리하는 패턴.
요청을 하는 쪽과 요청을 처리하는 쪽을 decoupling시킨다.
--> 요청을 처리하는 방법이 바뀌더라도, 호출자의 코드는 변경되지 않는다.
코드로 알아보기
불을 껏다 킬 수 있는 Button클래스가 있고 불에 해당하는 Light클래스가 있다고 해보자.
현재 코드에서 Button은 불을 끄도록 Light light 객체에서 on() 또는 off()로 요청한다. 즉 Button은 Invoker, Light는 receiver이다.
❗️문제점❗️
문제점 1. 그런데 버튼 눌렀을 때 불을 켜야 한다면 어떨까? 그렇게 되면 위의 Button클래스에서 light.off()를 light.on()으로 바꿔줘야 한다.
문제점 2. 또한 만약 Light가 아닌 Game 클래스를 만들서 Button이 Game을 시작하고 종료해야 한다면 모든 Light를 Game으로 수정해야할 것이다.
이와 같은 문제는 invoker와 receiver가 타이트하게 연결되어 있어서 발생하는 문제이다.
(MyApp은 Game을 직접 사용하고 있다.)
이제 이러한 문제를 커맨트 패턴을 사용하여 해결해보자.
먼저 Client또는 App이 사용하기 위한 Command 인터페이스가 필요하다.(상황에 따라 abstract클래스를 사용해도된다.)
이제 각 Command들은 해당 인터페이스를 구현하는 것이다.
(Command가 사용하는 Light혹은 Game 클래스들은 위에서 본것과 같아서 생략한다.)
물론 Command를 구현한 구체적인 Command클래스들은 자신들이 어떤 객체를 사용하고, 어떤 메소드를 실행해야하는지 구체적으로 알고 있어야 한다.
불을 키는 커맨드
불을 끄는 커맨드
불을 껏다 키는 Button은 구체적인 Command를 알 필요없이 Command인터페이스만을 사용하면 된다.
게임을 시작하는 커맨드
게임을 종료하는 커맨드
만약 Button클래스에서 버튼을 눌러 불을 끄거나 게임을 시작하거나 한다면 아래와 같을 것이다.
Button은 어떤 Command인지 구체적으로 알지 못하고 구체적인 Command는 외부에서 전달하는 것이다.
Button클래스가 아닌 MyApp에서 사용한다면 아래와 같다.
장점과 단점
장점
1. 기존 코드를 변경하지 않고 새로운 커맨드를 만들 수 있다. ( OCP)
2. 수신자의 코드가 변경되어도 호출자의 코드는 변경되지 않는다.
3. 커맨드 객체를 로깅, DB에 저장, 네트워크로 전송하는 등 다양한 방법으로 활용할 수 있다.
단점
코드가 복잡해지고 클래스가 많아진다.
출처: 인프런 백기선님 '코딩으로 학습하는 GoF 강의'
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4
'Design Pattern' 카테고리의 다른 글
16. 이터레이터 패턴 (Iterator pattern) (0) | 2021.12.26 |
---|---|
15. 인터프리터 패턴 (interpreter pattern) (0) | 2021.12.26 |
13. 책임 연쇄 패턴 (chain - of - responsibility) (0) | 2021.12.23 |
12. 프록시 패턴 (proxy pattern) (0) | 2021.12.23 |
11. 플라이웨이트 패턴 (flyweight pattern) (0) | 2021.12.22 |