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 |
Tags
- 브릿지 패턴
- 데커레이터 패턴
- 프로토타입
- 컴포지트
- 동적 데코레이터
- 디자인 패턴
- 컴포지트 패턴
- 단순한 빌더
- 디자인패턴
- 모던C++디자인패턴
- 브릿지
- 싱글턴
- 팩터리
- 동적 데커레이터
- 함수형 팩터리
- 데커레이터
- 컴포지트 빌더
- 싱글톤
- 프로토타입 패턴
- 내부 팩터리
- 빌더 패턴
- 싱글톤 패턴
- 팩터리 메서드
- 싱글턴 패턴
- 빌더
- 그루비 스타일 빌더
- 흐름식 빌더
- 추상 팩터리
- 프로토타입 중복처리
- 팩터리 패턴
Archives
- Today
- Total
GGym's Practice Notes
3-2. 팩터리_추상 팩터리/함수형 팩터리 본문
# 추상팩터리
그동안 객체 한개를 생성하는 경우를 살펴봤다. 드물지만 여러 종류의 연관된 객체를 생성해야 할 경우도 있다.
추상 팩터리는 그러한 경우를 위한 패턴이다.
뜨거운 차와 커피를 판매하는 카페를 운영해야한다고 가정했을때, 이 두 음료는 다른 장비를 이용해 만들어진다.
다음과 같이 뜨거운 음료를 추상화하는 HotDrink를 정의한다.
struct HotDrink{
virtual void prepare(int volume) = 0;
};
struct Tea : HotDrink{
void prepare(int volume) override{
cout << "Take tea bag, boil water, pour "<< volume <<"ml, add some lemon" << endl;
}
};
struct Coffee : HotDrink{
void prepare(int volume) override{
cout << "Grind some beans, boil water, pour " << volume << "ml, add cream, enjoy!" << endl;
}
};
make_drink 함수를 간단히 만들어 본다.
unique_ptr<HotDrink> make_drink(string type){
unique_ptr<HotDrink> drink;
if(type == "tea"){
drink = make_unique<Tea>();
drink->prepare(200);
}
else{
drink = make_unique<Coffee>();
drink->prepare(50);
}
return drink;
}
그런데 차와 커피를 만드는 장비는 다르다. 따라서 팩터리를 만들기로 한다.
struct HotDrinkFactory{
virtual unique_ptr<HotDrink> make() const = 0;
};
이 팩터리가 추상 팩터리이다.
어떤 특정 인터페이스를 규정하고 있지만 구현 클래스가 아닌 추상 클래스이다.
아래와 같은 자식 클래스로 구현클래스로서 만들 수 있다.
struct TeaFactory : HotDrinkFactory{
unique_ptr<HotDrink> make() const override{
return make_unique<Tea>();
}
};
struct CoffeeFactory : HotDrinkFactory{
unique_ptr<HotDrink> make() const override{
return make_unique<Coffee>();
}
};
이제 좀 더 상위 수준에서 다른 종류의 음료를 만들어야 한다고 가정해 보자
뜨거운 음료 뿐만 아니라 차가운 음료도 만들 수 있어야 한다.
이를 위해 DrinkFactory를 두어 사용 가능한 다양한 팩터리들에 대한 참조를 내부에서 가지도록 할 수 있다.
class DrinkFactory{
map<string, unique_ptr<HotDrinkFactory>> hot_factories;
public:
DrinkFactory(){
hot_factories["coffee"] = make_unique<CoffeeFactory>();
hot_factories["Tea"] = make_unique<TeaFactory>();
}
unique_ptr<HotDrink> make_drink(const string& name){
auto drink = hot_factories[name]->make();
drink->prepare(200);
return drink;
}
};
DrinkFactory df;
df.make_drink("coffee");
# 함수형 팩터리
팩터리라고 말할때 두 가지 중 하나를 의미한다.
- 객체를 어떻게 생성하는지 알고 있는 어떤 클래스
- 호출했을 때 객체를 생성하는 함수
2번째의 경우는 팩터리 메서드라고 생각될 수도 있지만 팩터리라고 부른다. 메서드는 객체의 멤버함수를 의미한다.
함수도 변수에 저장될 수 있다. 즉, 팩터리에 포인터를 저장하는 방법 대신에 200ml의 음료를 생성하는 절차 자체가 팩터리에 내장하게 할 수 있다.
class DrinkWithVolumeFactory{
map<string, function<unique_ptr<HotDrink>()>> factories;
public:
DrinkWithVolumeFactory(){
factories["tea"] = []{
auto tea = make_unique<Tea>();
tea->prepare(200);
return tea;
};
factories["coffee"] = []{
auto coffee = make_unique<Coffee>();
coffee->prepare(50);
return coffee;
};
}
unique_ptr<HotDrink> make_drink(const string& name);
};
저장된 팩터리를 직접 호출하는 과정을 다음과 같이 생략 할 수 있다.
inline unique_ptr<HotDrink> DrinkWithVolumeFactory::make_drink(const string& name){
return factories[name]();
}
이 코드는 동일하게 사용자가 이용할 수 있다.
DrinkWithVolumeFactory dv;
dv.make_drink("coffee");
'Design Pattern > Modern C++ 디자인패턴' 카테고리의 다른 글
4-2. 프로토타입_직렬화 (0) | 2020.04.17 |
---|---|
4-1. 프로토타입_중복처리 (0) | 2020.04.17 |
3-1. 팩터리_팩터리 메서드/팩터리/내부 팩터리 (0) | 2020.04.02 |
2-3. 빌더_컴포지트 빌더 (0) | 2020.03.31 |
2-2. 빌더_그루비-스타일 (0) | 2020.03.31 |