-
Notifications
You must be signed in to change notification settings - Fork 0
/
abstract_factory_v2.cc
132 lines (108 loc) · 3.06 KB
/
abstract_factory_v2.cc
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//
// Design pattern # Abstract factory
// - A wrapper around the creation of object in a single call.
//
// g++ -std=c++17 -Wall -Wextra -o abstract_factory_v2 abstract_factory_v2.cc
//
#include <iostream>
#include <memory>
#include <map>
enum class Type {
BLACK, LATTE, ICED, ICED_ESPRESSO,
};
struct Coffee {
virtual Type get_type() = 0;
virtual void prepare() = 0;
};
struct BlackCoffee: Coffee {
private:
Type type = Type::BLACK;
friend class HotCoffeeFactory;
// Keep it private to avoid creation of object outside the factory
BlackCoffee() {}
public:
Type get_type() override { return type; };
void prepare() override {
std::cout << "make coffee # black\n";
}
};
struct LatteCoffee: Coffee {
private:
Type type = Type::LATTE;
friend class HotCoffeeFactory;
// Keep it private to avoid creation of object outside the factory
LatteCoffee() {}
public:
Type get_type() override { return type; };
void prepare() override {
std::cout << "make coffee # latte\n";
}
};
struct IcedCoffee: Coffee {
private:
Type type = Type::ICED;
friend class ColdCoffeeFactory;
// Keep it private to avoid creation of object outside the factory
IcedCoffee() {}
public:
Type get_type() override { return type; };
void prepare() override {
std::cout << "make coffee # iced\n";
}
};
struct IcedEspressoCoffee: Coffee {
private:
Type type = Type::ICED_ESPRESSO;
friend class ColdCoffeeFactory;
// Keep it private to avoid creation of object outside the factory
IcedEspressoCoffee() {}
public:
Type get_type() override { return type; };
void prepare() override {
std::cout << "make coffee # iced espresso\n";
}
};
// A factory to create objects
struct AbstractFactory {
virtual std::unique_ptr<Coffee> make(Type type) = 0;
};
struct HotCoffeeFactory: AbstractFactory {
std::unique_ptr<Coffee> make(Type type) override {
if (type == Type::BLACK)
return std::unique_ptr<Coffee>(new BlackCoffee());
else if (type == Type::LATTE)
return std::unique_ptr<Coffee>(new LatteCoffee());
return nullptr;
}
};
struct ColdCoffeeFactory: AbstractFactory {
std::unique_ptr<Coffee> make(Type type) override {
if (type == Type::ICED)
return std::unique_ptr<Coffee>(new IcedCoffee());
else if (type == Type::ICED_ESPRESSO)
return std::unique_ptr<Coffee>(new IcedEspressoCoffee());
return nullptr;
}
};
struct CoffeeFactory {
std::map<Type, std::unique_ptr<AbstractFactory>> factories;
CoffeeFactory() {
factories[Type::BLACK] = std::make_unique<HotCoffeeFactory>();
factories[Type::LATTE] = std::make_unique<HotCoffeeFactory>();
factories[Type::ICED] = std::make_unique<ColdCoffeeFactory>();
factories[Type::ICED_ESPRESSO] = std::make_unique<ColdCoffeeFactory>();
}
std::unique_ptr<Coffee> make_coffee(Type type) {
return factories[type]->make(type);
}
};
//
// Entry function
//
int main() {
std::cout << "Design pattern # Abstract factory\n";
auto factory = std::make_unique<CoffeeFactory>();
auto cpu1 = factory->make_coffee(Type::BLACK);
cpu1->prepare();
return 0;
}