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 | 29 | 30 | 31 |
Tags
- BFS
- 비교 기반 정렬 알고리즘
- Trie
- Union-Find
- 트리
- command pattern
- C++ STL 정리
- 트리순회
- 디자인패턴
- 깊이 우선 탐색
- Factory method pattern
- object channel
- 스택
- 생성패턴
- 명령패턴
- 외적
- Unreal Collision
- 자료구조
- 동적 계획법
- Abstract Factory pattern
- 유니온-파인드
- flyweight pattern
- 팩토리패턴
- 두 직선사이 교점
- 정렬 알고리즘
- 관찰자(Observer) 패턴
- Set
- 분포 기반 정렬 알고리즘
- Queue
- 경량 패턴
Archives
- Today
- Total
KimMK
명령(Command) 패턴 본문
디자인 패턴 중 행위 패턴인 명령 패턴은 요구사항을 객체로 캡슐화하는 것이다. 실행될 기능을 캡슐화함으로써 주어진 여러 기능을 실행할 수 있는 재사용성이 높은 클래스를 설계하는 패턴으로 하나의 추상 클래스에 메서드를 만들어 각 명령이 들어오면 그에 맞는 서브 클래스가 선택되어 실행되는 특징을 갖는다.
즉, 함수 호출 자체를 객체로 감싸 캡슐화 한 것이다.
함수 호출을 객체로 만들었기 때문에 디커플링으로 코드가 유연하며,
redo(재실행), undo(실행 취소), 로깅, 입력키 변경 등과 같은 기능을 구현하는데 유용하다.
간단한 예시
리모컨을 제어하는 프로그램을 만든다고 가정할 때, 이 프로그램은 다양한 장치(에어컨, TV...)를 제어하는데 사용한다.
class Device {
public:
virtual void turnOn() = 0;
virtual void turnOff() = 0;
};
장치를 제어하는 추상 클래스를 만들고 모든 장치에 필요한 전원을 키고 끌 수 있는 가상 메서드(On/Off)를 포함시켜준다.
class Command {
public:
virtual ~Command() {}
virtual void execute() = 0;
protected:
Command(Device* device) : device(device) {}
Device* device;
};
class TurnOnCommand : public Command {
public:
TurnOnCommand(Device* device) : Command(device) {}
void execute() override {
device->turnOn();
}
};
class TurnOffCommand : public Command {
public:
TurnOffCommand(Device* device) : Command(device) {}
void execute() override {
device->turnOff();
}
};
그 후, 명령을 캡슐화하는 클래스를 만들고 이 클래스에서 실행할 장치와 메서드를 저장한다.
class RemoteControl {
public:
void pressOnButton(Command* command) {
command->execute();
}
void pressOffButton(Command* command) {
command->execute();
}
};
int main() {
Device* light = new Light();
Command* turnOnCommand = new TurnOnCommand(light);
Command* turnOffCommand = new TurnOffCommand(light);
RemoteControl remoteControl;
remoteControl.pressOnButton(turnOnCommand);
remoteControl.pressOffButton(turnOffCommand);
return 0;
}
리모컨 클래스에서 명령 객체를 생성해 execute 메서드를 통해 명령을 실행하도록 구현한다.
Command 패턴 | 장점 | 단점 |
- 유연성 명령을 캡슐화하므로 명령을 실행하는데 유연성을 제공한다. 명령의 인터페이스를 수정하거나 명령 자체를 교체해 새로운 명령을 쉽게 추가할 수 있다. - 확장성 새로운 명령을 추가할 때, 다른 명령들과 함께 동작하는 것을 변경할 필요없다. - 명령 기록 명령 패턴을 이용하면 실행된 명령의 기록을 저장할 수 있어 redo, undo, logging과 같은 기능을 제공할 수 있다. - 이식성 다양한 플랫폼과 언어에서 사용될 수 있으며, 적용 가능한 범위가 넓다. 클로저를 제대로 지원해주는 언어에서 적합하다. 클로저를 지원하지 않는 언어라면 클로저를 흉내내는 방법 중 하나라고 생각 ** C++에서 클래스형으로만 구현하는 것은 함수형에는 적합하지 않기 때문이다. 함수 포인터는 상태를 저장할 수 없고 람다는 메모리를 직접 관리해야 하므로 쓰기가 까다롭다. 또한 람다로 구현할 경우 누가 누굴 호출했는지 알기가 쉽지 않다. ** |
- 복잡성 명령 패턴은 구현이 비교적 복잡할 수 있다. 명령 객체와 수신 객체 간의 상호 작용을 구성해야 하기 때문이다. - 실행 속도 명령을 실행하는 데 추가적인 오버헤드가 발생한다. 객체를 생성하고 저장하는 것은 일반적으로 함수 호출보다 오버헤드가 크며, 명령 객체가 쌓이는 메모리 공간이 필요하기 때문에 메모리 사용량이 증가하고 불필요한 객체가 쌓이면 메모리 Leak이 발생할 수 있다. 따라서, 실행 속도가 느려질 수 있다. - 메모리 사용 실행 속도에서 언급했듯이, 명령 객체를 생성하고 유지해야 하기 때문에 메모리 공간을 할당할 수 밖에 없다. 명령의 수가 쌓이면 메모리 사용량이 증가한다. |
'C++ > 디자인 패턴' 카테고리의 다른 글
관찰자(Observer) 패턴 (0) | 2023.03.14 |
---|---|
싱글턴(Singleton) 패턴 (0) | 2023.03.12 |
경량(Flyweight) 패턴 (1) | 2023.03.11 |
디자인 패턴 (0) | 2023.03.11 |
팩토리 패턴 (0) | 2023.03.10 |