2학년 디자인패턴 Create Patterns

서지현·2021년 11월 18일
0

디자인패턴

목록 보기
1/3

Factory Method

  • 자식 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴

  • 예시

  • UML

  • product -> coffee

  • concreteProduct -> americano, mocha

#include<iostream>
#include<string>
using namespace std;

class Coffee{
public:
	virtual string Operation() = 0;
};

class Americano : public Coffee{
public:
	string Operation() {
		return "Americano";
	}
};
class Mocha : public Coffee{
public:
	string Operation() {
		return "Mocha";
	}
};

class Creator {
public:
	virtual Coffee* FactoryMethod() = 0;
	string create() {
		Coffee* product = this->FactoryMethod();
		string result = product->Operation();
		delete product;
		cout << result << endl;
		return result;
	}
};

class AmericanoCreator : public Creator {
public:
	Coffee* FactoryMethod() {
		return new Americano();
	}
};

int main() {
	Creator* creator = new AmericanoCreator();
	creator->create();
	delete creator;
	return 0;
}
  • 장점 : 기존 클라이언트 코드를 깨뜨리지 않고 새로운 유형의 제품을 프로그램에 도입할 수 있다.
  • 단점 : 새로운 많은 서브클래스르 도입해야 하기 때문에 코드가 복잡해질수 있다

Builder

  • 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들수 있다!

  • 예시

  • UML

#include<iostream>
#include<vector>
using namespace std;

class Product {
	vector<string> parts;
public:
	void put(string s) { parts.push_back(s); }
	void print() {
		for (int i = 0; i < parts.size(); i++) {
			if (parts[i] == parts.back())
				cout << parts[i];
			else
				cout << parts[i] << ", ";
		}
		cout << endl;
	}
};

class Builder {
public:
	virtual void Espresso() = 0;
	virtual void Water() = 0;
};

class Builder1 : public Builder {
private:
	Product* product;
public:
	Builder1() { product = new Product(); }
	void Espresso() { product->put("Espresso"); }
	void Water() { product->put("Water"); }

	Product* GetProduct() {
		Product* result = this->product;
		this->product = new Product();
		return result;
	}
};

class Director {
private:
	Builder* builder;
public:
	void set_builder(Builder* builder) {
		this->builder = builder;
	}
	void BuildEspresso() {
		this->builder->Espresso();
	}
	void BuildAmericano() {
		this->builder->Espresso();
		this->builder->Water();
	}
};

int main() {
	Director* director = new Director();
	Builder1* builder = new Builder1();
	Product* coffee = NULL;
	director->set_builder(builder);

	cout << "Making Americano" << endl;
	director->BuildAmericano();
	coffee = builder->GetProduct();
	coffee->print();
	cout << endl;

	cout << "Making Espresso" << endl;
	director->BuildEspresso();
	coffee = builder->GetProduct();
	coffee->print();

	return 0;
}
  • 장점 : 제품의 다양한 표현을 구축할 때 동일한 구성 코드를 재사용할 수 있습니다.
  • 단점 : 새 클래스가 여러개 있으면 코드의 복잡성이 증가합니다.

Abstract Factory

  • 다양한 구성 요소 별로 객체의 집합을 생성해야 하는 경우 상황에 알맞는 객체 생성이 가능하다

  • 예시

  • UML

#include<iostream>
#include<string>
using namespace std;

class AbstractProductA {
public:
	string coffee;
	virtual void make() = 0;
};

class CoffeeProduct1 : public AbstractProductA {
public:
	void make() {
		cout << "Americano created" << endl;
	}
};

class CoffeeProduct2 : public AbstractProductA {
public:
	void make() {
		cout << "latte created" << endl;
	}
};

class AbstractProductB {
public:
	string food;
	virtual void make() = 0;
};

class FoodProduct1 : public AbstractProductB {
public:
	void make() {
		cout << "Sandwich created" << endl;
	}
};

class FoodProduct2 : public AbstractProductB {
public:
	void make() {
		cout << "macaron created" << endl;
	}
};

class AbstractFactory {
public:
	virtual AbstractProductA* CreateProductA() = 0;
	virtual AbstractProductB* CreateProductB() = 0;
};

class ConcreteFactory1 : public AbstractFactory {
public:
	AbstractProductA* CreateProductA() {
		return new CoffeeProduct1();
	}
	AbstractProductB* CreateProductB() {
		return new FoodProduct1();
	}
};


class ConcreteFactory2 : public AbstractFactory {
public:
	AbstractProductA* CreateProductA() {
		return new CoffeeProduct2();
	}
	AbstractProductB* CreateProductB() {
		return new FoodProduct2();
	}
};

int main() {
	ConcreteFactory1* f1 = new ConcreteFactory1();
	AbstractProductA* product_a = NULL;
	AbstractProductB* product_b = NULL;
	product_a = f1-> CreateProductA();
	product_b = f1-> CreateProductB();
	product_a->make();
    product_b->make();

	ConcreteFactory2* f2 = new ConcreteFactory2();
	product_a = f2-> CreateProductA();
	product_b = f2-> CreateProductB();
	product_a->make();
	product_b->make();
	return 0;
}
  • 장점 : 구체적인 제품 코드와 클라이언트 코드 사이의 긴밀한 결합을 피할수 있다.
  • 단점 : 코드가 생각보다 복잡해질 수 있다

Prototype

  • 생성할 객체들의 타입이 프로토타입인 인스턴스로부터 결정되도록 하며, 인스턴스는 새 객체를 만들기 위해 자신을 복제하게 된다(복사 생성자)

  • 예시

  • UML

#include<iostream>
#include<string>
using namespace std;

class Prototype {
protected:
	string _size = "";
	string _color = "";
public:
	virtual Prototype* clone() = 0;
	void print() { cout << _size << "\t" << _color << endl; }
};

class ConcretePrototype1 : public Prototype {
public:
	ConcretePrototype1(string size, string color) {
		_size = size;
		_color = color;
	}
	Prototype* clone() {
		return new ConcretePrototype1(*this);
	}
};

class ConcretePrototype2 : public Prototype {
public:
	ConcretePrototype2(string size) {
		_size = size;
	}
	Prototype* clone() {
		return new ConcretePrototype2(*this);
	}
};

int main() {
	Prototype* prototype1 = new ConcretePrototype1("tall", "black");
	Prototype* copy1 = prototype1->clone();
	prototype1->print();
	copy1->print();
	Prototype* prototype2 = new ConcretePrototype2("venti");
	Prototype* copy2 = prototype2->clone();
	prototype2->print();
	copy2->print();
	return 0;
}
  • 장점 : 구체적인 클래스에 연결하지 않고 객체를 복제할 수 있다.
  • 단점 : 순환 참조가 있는 복잡한 개체를 복제하는 것은 매우 까다로울 수 있다.

Singleton

  • 클래스에 인스턴스가 하나만 있는지 확인하고 이에 대한 전역 접근을 제공합니다

  • 예시

  • UML

#include<iostream>
#include<string>
using namespace std;

class Singleton {
public:
	static Singleton* getInstance();
	void print() {
		cout << val << endl;
	}
	void inc() {  val++;  }
private:
	static Singleton* _instance;
	Singleton() { val = 3; }
	int val;
};

Singleton* Singleton::_instance = 0;
Singleton* Singleton::getInstance() {
	if (_instance == 0)
		_instance = new Singleton;
	return _instance;
}

int main() {
	Singleton *s = Singleton :: getInstance();
	s->print();

	Singleton* y = Singleton::getInstance();
	y->print();
	y->inc();
	s->print();

	return 0;
}
  • 장점 : 성능향상, 메모리 낭비막음, 전역 데이터 공유가 늘어남
  • 단점 : 멀티스레딩 문제가 발생할 수 있다
profile
안녕하세요

0개의 댓글

관련 채용 정보