명령 객체와 일련의 처리 객체를 포함하는 디자인 패턴
예시
UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
using namespace std;
class Handler {
public:
	virtual Handler* SetNext(Handler* handler) = 0;
	virtual string Handle(string request) = 0;
};
class AbstractHandler : public Handler {
private:
	Handler* next_handler_;
public:
	AbstractHandler() : next_handler_(nullptr) { }
	Handler* SetNext(Handler* handler) {
		this->next_handler_ = handler;
		return handler;
	}
	string Handle(string request) {
		if (this->next_handler_) { return this->next_handler_->Handle(request); }
		return {};
	}
};
class AHandler : public AbstractHandler {
public:
	string Handle(string request) override {
		if (request == "A") { return "Request A Done"; }
		else { return AbstractHandler::Handle(request); }
	}
};
class BHandler : public AbstractHandler {
public:
	string Handle(string request) override {
		if (request == "B") { return "Request B Done"; }
		else { return AbstractHandler::Handle(request); }
	}
};
int main() {
	AHandler* a = new AHandler;
	BHandler* b = new BHandler;
	a->SetNext(b);
	vector<string> requests = { "B", "C", "A" };
	for (const string& f : requests) {
		const string result = a->Handle(f);
		if (!result.empty()) {
			cout << result << endl;
		}
		else {
			cout << "Request " << f << " left untouched." << endl;
		}
	}
	return 0;
}
장점
단점
요청을 객체의 형태로 갭슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수, 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다
예시
UML
invoker = button, Receiver = product
#include<iostream>
#include <list> 
#include<string>
#include<vector>
using namespace std;
class Receiver {
public:
	void execute(const string& a) {
		cout << a << " done" << endl;
	}
};
class Command {
public:
	virtual void Execute() const = 0;
};
class Command1 : public Command {
private:
	Receiver* receiver_;
	string a_;
public:
	Command1(Receiver* receiver, string a) : receiver_(receiver), a_(a) { }
	void Execute() const override { this->receiver_->execute(this->a_); }
};
class Command2 : public Command {
private:
	Receiver* receiver_;
	string a_;
	string b_;
public:
	Command2(Receiver* receiver, string a, string b) : receiver_(receiver), a_(a), b_(b) { }
	void Execute() const override {
		this->receiver_->execute(this->a_);
		this->receiver_->execute(this->b_);
	}
};
class Invoker {
private:
	Command* c_;
public:
	void setCommand(Command* command) {
		this->c_ = command;
	}
	void Do() {
		this->c_->Execute();
	}
};
int main() {
	Invoker* invoker = new Invoker;
	Receiver* receiver = new Receiver;
	invoker->setCommand(new Command1(receiver, "Americano"));
	invoker->Do();
	invoker->setCommand(new Command2(receiver, "Americano", "Mocha"));
	invoker->Do();
	return 0;
}
반복자를 사용하여 컨테이너를 가로지르며 컨테이너의 요소들에 접근하는 디자인패턴
예시, UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
using namespace std;
class Data
{
public:
	Data(int
		a = 0) : m_data_(
			a) {}
	void setData
	(int
		a) {
		m_data_ =
			a;
	}
	int getData() {
		return m_data_;
	}
private:
	int m_data_;
};
typedef typename std::vector<Data>::iterator iter_type;
class Iterator {
public:
	Iterator(vector<Data>* p_data) : m_p_data_(p_data) { First(); }
	void First() { m_it_ = m_p_data_->begin(); }
	void Next() { m_it_++; }
	bool IsDone() { return (m_it_ == m_p_data_->end()); }
	iter_type Current() { return m_it_; }
private:
	vector<Data>* m_p_data_;
	iter_type m_it_;
};
int main() {
	vector<Data> cont;
	Data a(100), b(1000), c(10000);
	cont.push_back(a);
	cont.push_back(b);
	cont.push_back(c);
	Iterator* it = new Iterator(&cont);
	for (it->First(); !it->IsDone(); it->Next()) {
		std::cout << it->Current()->getData() << std::endl;
	}
	return 0;
}
중재자는 개체가 서로를 명시적으로 참조하지 않도록하여 느슨한 결합을 촉진합니다
예시
UML
Colleague1, Colleague2는 소통을 하려고 하지 않는다
#include<iostream>
#include <list> 
#include<string>
#include<vector>
using namespace std;
class Mediator {
public:
	virtual void Notify(BaseComponent* sender, string event) const = 0;
};
class BaseComponent {
protected:
	Mediator* mediator_;
public:
	BaseComponent(Mediator* mediator = nullptr) : mediator_(mediator) {
	}
	void set_mediator(Mediator* mediator) {
		this->mediator_ = mediator;
	}
};
class ConcreteMediator : public Mediator {
private:
	Component1* component1_;
	Component2* component2_;
public:
	ConcreteMediator(Component1* c1, Component2* c2) : component1_(c1), component2_(c2) {
		this->component1_->set_mediator(this);
		this->component2_->set_mediator(this);
	}
	void Notify(BaseComponent* sender, std::string event) const override {
		if (event == "A") { this->component1_->Msg(); }
		if (event == "B") { this->component2_->Msg(); }
	}
};
class Component1 : public BaseComponent {
public:
	void DoA() { this->mediator_->Notify(this, "A"); }
	void Msg() { cout << "Want to grab lunch?" << endl; }
};
class Component2 : public BaseComponent {
public:
	void DoB() { this->mediator_->Notify(this, "B"); }
	void Msg() { cout << "No" << endl; }
};
int main() {
	Component1* c1 = new Component1;
	Component2* c2 = new Component2;
	ConcreteMediator* mediator = new ConcreteMediator(c1, c2);
	c1->DoA();
	c2->DoB();
	delete c1;
	delete c2;
	delete mediator;
	return 0;
}
객체를 이전상태로 되돌릴수 있는 기능을 제공 -> version control system(git)
예시
UML
originator -> 수정
memento -> state
caretaker -> memento manager
#include<iostream>
#include <list> 
#include<string>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
class Memento {
public:
	virtual int getState() const = 0;
};
class ConcreteMemento : public Memento {
private:
	int state_;
public:
	ConcreteMemento(int state) : state_(state) {
		this->state_ = state;
	}
	int getState() const {
		return this->state_;
	}
};
class Originator {
private:
	int state_;
public:
	Originator(int state) : state_(state) {
		cout << "Current State: " << this->state_ << endl;
	}
	void DoSomething() {
		this->state_ += rand() % 10;
		cout << "State has been changed to: " << this->state_ << endl;
	}
	Memento* Save() {
		return new ConcreteMemento(this->state_);
	}
	void Restore(Memento* memento) {
		this->state_ = memento->getState();
		cout << "State has been changed to: " << this->state_ << endl;
	}
};
class Caretaker {
private:
	std::vector	<Memento*> mementos_;
	Originator* originator_;
public:
	Caretaker(Originator* originator) : originator_(originator) {
		this->originator_ = originator;
	}
	void Backup() {
		cout << "Saving state...\n";
		this->mementos_.push_back(this->originator_->Save());
	}
	void Undo() {
		if (!this->mementos_.size()) {
			return;
		}
		Memento* memento = this->mementos_.back();
		this->mementos_.pop_back();
		std::cout << "Restoring state to: " << memento->getState() << endl;
		try {
			this->originator_->Restore(memento);
		}
		catch (...) {
			this->Undo();
		}
	}
};
int main() {
	srand(static_cast<unsigned int>(std::time(NULL)));
	Originator* originator = new Originator(0);
	Caretaker* caretaker = new Caretaker(originator);
	caretaker->Backup();
	originator->DoSomething();
	caretaker->Backup();
	originator->DoSomething();
	caretaker->Undo();
	caretaker->Undo();
	return 0;
}
객체의 상태변화가 있을 때마다 메서드, 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하는 패턴
예시
UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
class IObserver {
public:
	virtual void Update(const string& message_from_subject) = 0;
};
class Observer : public IObserver {
public:
	Observer(Subject& subject) : subject_(subject) {
		this->subject_.Attach(this);
	}
	void Update(const std::string& message_from_subject) override {
		message_from_subject_ = message_from_subject;
		PrintInfo();
	}
	void PrintInfo() {
		cout << "Observer: New message arrived --> [ " << this->message_from_subject_ << " ]" << endl;
	}
private:
	std::string message_from_subject_;
	Subject& subject_;
};
class ISubject {
public:
	virtual void Attach(IObserver* observer) = 0;
	virtual void Notify() = 0;
};
class Subject : public ISubject {
public:
	void Attach(IObserver* observer) { list_observer_.push_back(observer); }
	void Notify() {
		std::list<IObserver*>::iterator iterator = list_observer_.begin();
		while (iterator != list_observer_.end()) {
			(*iterator)->Update(message_);
			++iterator;
		}
	}
	void CreateMessage(string message) {
		this->message_ = message;
		Notify();
	}
private:
	list<IObserver*> list_observer_;
	string message_;
};
int main() {
	Subject* subject = new Subject;
	Observer* observer1 = new Observer(*subject);
	Observer* observer2 = new Observer(*subject);
	Observer* observer3 = new Observer(*subject);
	subject->CreateMessage("New Drink Available");
	return 0;
}
장점 : 객체 간의 관계를 런타임에 설정할 수 있다
단점 : 무작위로 통보된다
객체의 내부 상태가 변경될 때 객체가 동작을 변경하도록 허용합니다. 개체는 클래스를 변경하는 것으로 나타난다
예시
UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
class Context;
class State {
protected:
	Context* context_;
public:
	void set_context(Context* context) {
		this->context_ = context;
	}
	virtual void Handle1() = 0;
};
class Context{
private:
	State* state_;
public:
	Context(State* state) : state_(nullptr) {
		this-> TransitionTo(state);
	}
	~Context() { delete state_; }
	void TransitionTo(State* state) {
		if(this->state_ != nullptr)
			delete this->state_;
		this->state_ = state;
		this->state_->set_context(this);
	}
	void Request1() {
		this->state_->Handle1();
	}
};
class ReadyState : public State {
public: void Handle1();
};
class RunState : public State {
public: void Handle1();
};
class OffState : public State {
public: void Handle1();
};
void ReadyState::Handle1() {
	cout << "[Ready State] --> [Run State]" << endl;
	this->context_->TransitionTo(new RunState);
};
void RunState::Handle1() {
	cout << "[Run State] --> [Off State]" << endl;
	this->context_->TransitionTo(new OffState);
};
void OffState::Handle1() {
	cout << "[Off State] --> [Ready State]" << endl;
	this->context_->TransitionTo(new ReadyState);
};
int main() {
	Context* context = new Context(new OffState);
	context->Request1();
	context->Request1();
	context->Request1();
	return 0;
}
특정한 계열의 알고리즘들을 정의하고 각 알고리즘을 캡슐화하여 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다
예시
UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
class Strategy {
public:
	virtual void doAlgorithm() const = 0;
};
class ConcreteStrategyA : public Strategy {
public:
	void doAlgorithm() const {
		cout << "Algorithm A is applied" << endl;
	}
};
class ConcreteStrategyB : public Strategy {
	void doAlgorithm() const {
		cout << "Algorithm B is applied" << endl;
	}
};
class Context
{
private:
	Strategy* strategy_;
public:
	Context(Strategy* strategy = nullptr) : strategy_(strategy) { }
	void set_strategy(Strategy* strategy)
	{
		delete this->strategy_;
		this->strategy_ = strategy;
	}
	void makeCoffee() const
	{
		this->strategy_->doAlgorithm();
	}
};
int main()
{
	Context* context = new Context(new ConcreteStrategyA);
	context->makeCoffee();
	context->set_strategy(new ConcreteStrategyB);
	context->makeCoffee();
	return 0;
}
state pattern이랑 유사
장점
단점
작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기합니다.
예시
UML
Template Method -> factory method, abstract factory의 근본이 된다
class AbstractClass
{
public:
	void TemplateMethod() {
		this
			->BaseOperation1();
		this
			->RequiredOperation1();
		this
			->BaseOperation2();
		this
			->RequiredOperation2();
	}
protected:
	void BaseOperation1() const
	{
		cout << "Base Operation 1" << endl;
	}
	void BaseOperation2() const
	{
		cout << "Base Operation 2" << endl;
	}
	virtual void RequiredOperation1() const = 0;
	virtual void RequiredOperation2() const = 0;
};
장점 : 클라이언트가 큰 알고리즘의 특정 부분만 재정의하도록 하여 알고리즘의 다른 부분에서 발생하는 변경 사항의 영향을 덜 받도록 할 수 있습니다.
단점 : 일부 클라이언트는 제공된 알고리즘의 골격에 의해 제한될 수 있습니다.
알고리즘을 객체 구조에서 분리시키는 디자인 패턴이다.
클래스에서 data영역과 function영역을 나눈다
예시
UML
#include<iostream>
#include <list> 
#include<string>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
class Component{
public:
	virtual void Accept(Visitor* visitor) = 0;
};
class Americano : public Component{
public:
	void Accept(Visitor* visitor) {
		visitor	-> VisitConcreteComponentA(this);
	}
};
class Latte : public Component{
public:
	void Accept(Visitor* visitor) {
		visitor	-> VisitConcreteComponentB(this);
	}
};
class Visitor {
public:
	virtual void VisitConcreteComponentA(const Americano* element) = 0;
	virtual void VisitConcreteComponentB(const Latte* element) = 0;
};
class ConcreteVisitor1 : public Visitor {
public:
	void VisitConcreteComponentA(const Americano* element) {
		cout << "Americano" << endl;
	}
	void VisitConcreteComponentB(const Latte* element) {
		cout << "Latte" << endl;
	}
};
int main() {
	Component* arr[2] = { new Americano, new Latte };
	ConcreteVisitor1* visitor1 = new ConcreteVisitor1;
	for (int i = 0; i < 2; i++) {
		arr[i]->Accept(visitor1);
	}
	return 0;
}
단점 : 방문자는 개인 필드 및 작업해야 하는 요소의 메서드에 대한 필수 액세스 권한이 부족할 수 있다.