Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 자취준비
- 알고리즘
- HeadFirstDesignPatterns
- 캡쳐링
- 자료구조
- 동적계획법
- 실업급여
- 청년내일채움공제
- 막대기자르기
- 네트워크
- C++
- 후니의쉽게쓴시스코라우팅
- 사회초년생
- 회사폐업
- 순열
- 모여봐요동물의숲
- 코딩테스트
- 생애첫계약
- array
- 프로그래머스
- 부분합알고리즘
- 전화영어
- 정보
- 후니의쉽게쓴시스코네트워킹
- 취업사실신고
- 실업인정인터넷신청
- IT기초
- 정보처리기사개정
- 튜터링
- leetcode
Archives
- Today
- Total
따봉도치야 고마워
Head First Design Patterns : (6)커맨드 패턴 본문
커맨드 패턴
- 커맨드 패턴을 이용해 요청 내역을 객체로 캡슐화 할 수 있고, 매개변수를 사용해 여러 가지 다른 요청을 집어 넣을 수 있다.
- 또한 요청 내역을 큐에 저장하거나 로그로 기록할 수 있고, 작업취소 기능도 지원이 가능하다.
- 요청을 하는 객체와(요청), 그 요청을 수행하는 객체(동작)를 분리 할 수 있음.
- 리시버에 대한 동작이 추가될 때마다 잡다한 클래스가 많이 추가될 수 있다는 단점이 있음.
- 요청 자체를 리시버한테 넘기지 않고 자신이 처리하는 '스마트' 커맨드 객체도 종종 사용
커맨드 패턴 구조
- 수신자 (Receiver) : 실제 행동을 하는 객체
- 커맨드 (Command) : 리시버와 리시버의 특정 행동을 호출하는 객체, 버튼에 할당될 행위
- 발동자 (Invoker) : 커맨드를 저장해놓고, 행위 발동 시 커맨드 호출
- 클라이언트 (Client) : 커맨드 객체를 생성, Invoker에 커맨드 객체를 할당
- 클라이언트는 커맨드 객체를 생성하고, 리시버를 설정해줌
- Invoker는 커맨드 객체를 저장하고, 해당 커맨드의 excute() 메소드를 호출해 작업을 요청함
- 커맨드 객체에선 리시버와 특정 작업을 연결해줌. excute() 실행 시 리시버에 있는 메소드를 호출하게 됨.
활용
- 요청을 큐에 저장 : 커맨드를 작업 큐에 저장 후, 나머지 한 쪽에선 스레드가 하나씩 작업을 받아 수행한다. (excute)
- 요청을 로그에 저장 : 커맨드에 store(), load() 메소드 추가 후, 각 커맨드가 실행될 때 디스크에 내역을 저장하고, 시스템 다운 시 복구한다.
객체 마을 식당 예제
- 손님(클라이언트)이 주문을 하면 주문서(커맨드 객체)에 메뉴 항목이 캡슐화됨
- 주문서에는 orderUp() 메소드와 누가 처리할 것인지(리시버)에 대한 정보가 있음
- 웨이터는 해당 주문서에 있는 orderUp() 메소드만 호출해줌.
리모컨 API 설계 예제 - 커맨드 패턴 적용
- 리모컨 버튼 별로 각각 장치 제어 기능을 추가하려고 한다.
- 리모컨 버튼 코드에 일일히 각 장치 제어 기능을 달아주게 되면, 장치가 추가/제거/변경 될 때 마다 리모컨 코드를 수정해줘야 한다.
- 커맨드 패턴을 이용해, 리모컨에선 커맨드 객체만 가지고 있고 실제로 어떤 작업이 처리되는지는 모르게 한다.
<커맨드 객체 만들기>
1) Command 인터페이스 생성
public interface Command{
public void excute();
}
2) 전등을 켜기 위한 커맨드 클래스 구현
public class LightOnCommand implements Command{
Light light;
public LightOnCommand(Light light){
this.light = light;
//여기서 light가 리시버 객체가 됨
}
public void excute(){
light.on();
}
}
<커맨드 객체 사용하기>
public class RemoteControl{
//invoker 역할을 할 클래스
Command[] onCommands;
Command[] offCommands;
public RemoteControl(){
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
//null 객체를 따로 생성해서 초기화 해주면 클라 쪽에서 null check 안해도 됨
for(int i=0; i<7; i++){
onCommand[i] = noCommand;
offCommand[i] = noCommand;
}
}
public void setCommand(int slot, Command onCommand, Command offCommand){
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPressed(int slot){
//on 버튼 눌릴 때 호출될 메소드
onCommand[slot].excute();
}
public void offButtonWasPressed(int slot){
//off 버튼 눌릴 때 호출될 메소드
offCommand[slot].excute();
}
}
- 버튼이 하나인 리모컨 코드
- 클라이언트에서 해당 클래스의 객체(Invoker)를 만들어 2)커맨드 객체를 세팅 및 명령 요청
리모컨 API 설계 예제 - Undo 기능 추가
- Command 인터페이스에 undo() 메소드 추가
- 각 커맨드 객체에 excute()와 반대되는 행동을 하는 undo() 메소드 구현
- 상태 저장이 필요한 경우라면 상태 변수 추가해 구현
- ex) 선풍기 속도 변경
- RemoteControl에 가장 마지막으로 누른 버튼을 기록하고, undo버튼을 처리하는 부분 추가
public class RemoteControlWithUndo{
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteControl(){
..
undoCommand = noCommand;
}
..
public void onButtonWasPressed(int slot){
onCommand[slot].excute();
undoCommand = onCommand[slot];
}
public void offButtonWasPressed(int slot){
offCommand[slot].excute();
undoCommand = offCommand[slot];
}
//undo 버튼 클릭 시 마지막으로 눌렀던 버튼(커맨드)의 undo() 메소드 호출
public void undoButtonWasPushed(){
undoCommand.undo();
}
}
리모컨 API 설계 예제 - Macro 기능 추가 (여러기능 한 번에)
- 여러 가지 커맨드를 한 번에 실행할 수 있는 새 커맨드 생성
- ON/OFF 커맨드들을 생성하고 배열로 만들어 MacroCommand에 넣어줌
- MacroCommand를 버튼에 할당
//1
public class MacroCommand implements Command{
Command[] commands;
//리시버가 커맨드 자체가 되는 듯?
public MacroCommand(Command[] commands){
this.commands = commands;
}
public void execute(){
for(int i=0; i<commands.length; i++){
commands[i].excute();
}
}
}
Command[] partyOn = {lightOn, stereoOn, tvOn, hottubOn};
Command[] partyOff = {lightOff, stereoOff, tvOff, hottubOff};
//2
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
//3
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
NOTE
- null 객체 활용하기
'프로그래밍 > 공부' 카테고리의 다른 글
Head First Design Patterns : (8)템플릿 메소드 패턴 (0) | 2020.09.23 |
---|---|
Head First Design Patterns : (7)어댑터 패턴과 퍼사드 패턴 (0) | 2020.09.21 |
Head First Design Patterns : (5)싱글턴 패턴 (0) | 2020.09.15 |
Head First Design Patterns : (4)팩토리 패턴 (0) | 2020.09.14 |
Head First Design Patterns : (3)데코레이터 패턴 (0) | 2020.09.11 |
Comments