3. • 본 PPT는 Design Patterns Study를 위해 작성되었습니다.
• Study에 사용한 교재는 한빛미디어에서 나온
• [Head First Desgin Patterns]을 사용하였습니다.
• Written by 서울시립대 이희태 For study with
NHN NEXT2기 조현호
서 울 시 립 대 이 희 태
4.
5. 안녕하십니까?
저희가 새로 개발한 홈 오토메이션 리모컨의 API 디자인을 의뢰하고자 합니
다. 저희 회사에서 개발 중인 최신형 리모컨 시제품을 동봉해 드리겠습니다.
이 리모컨에는 일곱 가지 프로그래밍이 가능한 슬롯과 각 슬롯에 대한
ON/OFF 스위치가 있습니다. 각 슬롯은 다양한 가정용 기기에 연결할 수 있
습니다. 리모컨에는 작업취소 버튼도 장착되어 있습니다.
그리고 조명, 팬, 욕조, 오디오를 비롯한 장비들을 제어하기 위한 용도로 다
양한 업체에서 공급받은 자바 클래스들을 CD에 동봉해서 보내드립니다. 각
슬롯을 한 가지 기기 또는 하나로 엮어 있는 일련의 기기들에 할당할 수 있도
록 리모컨을 프로그래밍하기 위한 API를 제작해주시길 부탁 드립니다.
여러분께서 설계하신 디자인을 하루 빨리 볼 수 있기를 기대하고 있겠습니
다. 건승을 기원합니다.
빌 “X – 10” 톰슨, CEO
디자인 의뢰가 들어왔네요.
6. 동봉된 리모컨을 살펴봅시다.
1번 슬롯에 연결되는
가전제품 제어
2번 슬롯에 연결되는
가전제품 제어
. . .
버튼들이 쭉 나열된다.
7가지 프로그래밍이
가능한 슬롯. 각 슬롯
에 원하는 제품을 연
결한 후 우측의 버튼
으로 조작할 있다.
Undo 버튼 : 마지막으
로 누른 버튼에 대한
명령 취소
제어할 수 있는 제품
의 이름이 등록
8. 리모컨 API 디자인 설계
지금 바로 위의 가전제품 클래스들을
리모컨에 부착하도록 설계하면 어떨까?
문제점
1. 바뀌는 부분을 따로 캡슐화하지 않았다.
2. 상위 클래스가 아닌 구체적인 클래스들에 의존하고 있다.
3. 리모컨에 부착하는 구체적인 가전제품 클래스들이 새로 추가,변경될
때마다 리모컨의 코드를 고쳐야 한다.
4. 가전제품에 따라 리모컨 on/off버튼에 해당되는 메소드 호출이 다 달
라야만 한다.
5. 리모컨에서 가전제품 클래스에 대해 정보은닉이 되고 있지 않는다.
9. 즉,
리모컨의 버튼과 가전제품의 특정 기능(ex. On, off)들이 전혀
분리되어 있지 않다. Client에서 특정 작업 요청이 이루어질
때 그 요청 호출을 캡슐화할 필요가 있다.
Command Pattern
을 사용한다!
12. 연어스테이크,
카바(cava)
웨이트리스와 요리사가 구분되어있다.
이 둘은 Order객체 – 주문서 – 를 통해서 소통할 뿐이다.
요리사는 요리에 필요한 정
보만 가지고 있다. 요리를 하
지 주문을 받지는 않는다.
웨이트리스는 주문서를 식사
를 준비시킨다.
요리를 하지 않는다.
16. COMMAND PATTERN이란?
Def : 커맨드 패턴을 이용하면 요구 사항을 객체로 캡슐
화할 수 있으며, 매개 변수를 써서 여러 가지 다른 요구
사항을 집어 넣을 수 있다. 또한 요청 내역을 큐에 저장
하거나 로그로 기록할 수도 있으며, 작업 취소 기능도 지
원 가능하다.
17. UML 다이어그램
+setCommand
()
커맨드 객체에게 Execute()
를 실행하도록 요청 <Interface>
매개변수로 command객체를 받음
ConcreteCommand를 생성한 후 그 객체에 특
정 Receiver를 넣어줌
구현된 Excetute()메소드에서는 receiver의 메
소드(Action())를 호출하여 요청된 작업을 수
행 (호출의 캡슐화)
27. Interface에 undo() 메소드를 선언해준다.
concreteCommand객체에서 undo() 메소드를 구현한
다. On Command객체라면 -> off로, Off Command객
체라면 On으로 작업취소 명령을 정의해준다.
Undo()가 추가된 Command객체
28. Invoker
undoCommand객체를 멤버변수로 넣어주고…
여기에도 noCommand 대입
사용자가 버튼을 누르면 우선 해당 Command
를 실행한 뒤(=execute() 호출한 후), 바로 그
객체의 레퍼런스를 undoCommand 변수에 할
당해준다.
사용자가 undoButton을 누르면 현재 저장된
undoCommand객체의 undo()메소드를 호출한다.
그러면 마지막으로 했던 작업이 취소된다.
30. Q/A
Q1. 항상 리시버가 필요한가요? 커맨드 객체에서 execute()를 구현해 버리면 안
되나요?
ans) 일반적으로 리시버에 있는 행동을 호출하는 “더미” 커맨드 객체를 만든다.
하지만 요구사항의 전부는 아니더라도 대부분을 요구하는 “스마트” 커맨드 객체를
만드는 경우도 자주 볼 수 있다. 물론 커맨드객체에서 대부분의 행동을 처리해도
된다. 하지만 그렇게 하면 여기에서 우리가 했던 수준으로 인보커와 리시버를 분리
시키는 것이 불가능해지고, 리시버를 이용해서 커맨드를 매개변수화하는것도 할
수 없다.
Q2. 작업 취소를 할 때 히스토리 기능은 어떻게 구현할 수 있나요? 즉, UNDO버튼
을 여러 번 누를 수 있도록 하려면 어떻게 해야 하나요?
ans) 간단하다. 앞에서는 undoCommand에 마지막으로 실행한 커맨드에 대한 레
퍼런스를 그냥 대입했는데, 여기서는 스택을 이용하여 이전에 실행한 커맨드를 순
서대로 저장하면 된다. 그리고 나서 사용자가 undo버튼을 누를 때마다 스택의 맨
위에서부터 항목을 꺼내서 undo() 메소드를 호출하기만 하면 된다.