본문 바로가기
SWE/C++ OOP

[디자인 패턴] Command Pattern 커맨드 패턴 | 디자인 패턴의 3종류 | 행동 패턴

by S나라라2 2021. 9. 7.
반응형

 

디자인 패턴의 3가지 타입

 

 

디자인 패턴의 3가지 타입

디자인 패턴들은 크게 3가지 타입으로 나눌 수 있다.

- 생성 패턴 (Creational Patterns)

- 구조 패턴 (Structural Patterns)

- 행동 패턴 (Behavioral Patterns)

 

생성 패턴 Creational Patterns

이름에서 볼 수 있듯이 생성 패턴은 클래스 생성을 위한 디자인이다. 따라서 클래스 생성 패턴 또는 객체 생성 패턴이라고 불리기도 한다. 

예시로는 팩토리 패턴, 싱글턴 패턴, 프로토타입 패턴, 빌더 패턴 등이 있다. 

 

구조 패턴 Structural Patterns

구조 패턴은 클래스의 구조, 구성(composition)과 관계가 깊다. 대부분의 구조 패턴의 목적은 각 클래스들의 구성을 최소화하는 것에 있다.

구조 패턴의 예로는 데코레이터 패턴, 어댑터 패턴, 브리지 패턴, 파사드 패턴, 프록시 패턴, 합성 패턴, 플라이웨이트 패턴 등이 있다.

 

행동 패턴 Behavioral Patterns

행동 패턴은 하나의 클래스가 다른 클래스들과 어떻게 소통하는지에 초점을 두고 있다.

예시로는 옵저버 패턴, 템플릿 메서드 패턴, 반복자 패턴, 전략 패턴, 책임 연쇄 패턴, 해석자 패턴, 방문자 패턴, (그리고 오늘 공부할) 커맨드 패턴, 등이 있다.

 

 

출처:

The 3 Types of Design Patterns All Developers Should Know (with code examples of each)

https://www.freecodecamp.org/news/the-basic-design-patterns-all-developers-need-to-know/


 

 

커맨드 패턴 Command Pattern

 

커맨드 패턴의 목적은 결합도를 낮추는 것이다. 결합도를 낮추기 위해 객체끼리 직접적인 호출을 하지 않고, 어떤 작업을 요청하는 쪽하고 그 작업을 처리하는 쪽을 분리시킨다. 그리고 작업 요청 객체를 캡슐화하여 주고 받는다.

 

식당을 예로 들어보자.

식당에는 고객과 요리사가 있다.

고객은 요리사에게 직접 음식 주문을 해도 되지만, 여기에 웨이터(인보커)를 추가하여 직접적인 호출을 하지 않는다.

웨이터는 주문을 받을 때 정해진 규칙에 따라 주문서(커맨드객체)를 이용하여 받는다.

그리고 요리사는 웨이터로부터 주문서를 전달받아 요리를 수행한다.

 

 

주문서는 주문한 메뉴를 캡슐화하고 있다. 주문을 그저 '전달'만하는 웨이터는 주문 내용을 인지할 필요 없이 주문서를 요리사에게 전달만 하면 된다. 즉 웨이터와 요리사가 완전히 분리되어 있다.

코드 관점에서 수행 순서를 살펴보면 다음과 같다. 

1. Client(고객)는 Command(주문서) 객체를 생성한다. 

2. Client(고객)에서 Invoker(웨이터) 객체의 SetCommand 메소드를 호출해서 커맨드 객체를 넘겨준다.

3. Invoker(웨이터)에서 Command(주문서) 객체의 execute() 메소드를 호출해서,

4. Receiver(요리사)에 있는 특정 행동들 action1(), action2(), ... 를 수행시킨다.

 

class Command
{
public:
	Command(std::string food) { m_food = food; };
	~Command() {};

private:
	std::string m_food;

public:
	void execute() { std::cout << m_food << std::endl; };
};

 

class Receiver
{
public:
	Receiver() {};
	~Receiver() {};

public:
	void action(Command* command) 
	{
		std::cout << "I'm a chef. I'm cooking ";
		command->execute();
	};
};

 

class Invoker
{
public:
	Invoker(Receiver* receiver) { m_receiver = receiver; };
	~Invoker() {};

private:
	Receiver* m_receiver;
	Command* m_command;

public:
	void setCommand(Command* command)
	{
		std::cout << "I'm a waiter. I got order." <<std::endl;
		m_command = command;
		m_receiver->action(m_command);
	};
};

 

int main()
{
    std::cout << "[Command Pattern Example] \n";

	Receiver* receiver = new Receiver();
	Invoker* invoker = new Invoker(receiver);


	std::cout << "\n I'm a client. I'm ordering some food.\n";
	Command* command1 = new Command("Pizza");
	invoker->setCommand(command1);

	std::cout << "\n I'm a client. I'm ordering some food.\n";
	Command* command2 = new Command("Pasta");
	invoker->setCommand(command2);
}

 

반응형