-
Notifications
You must be signed in to change notification settings - Fork 0
/
Flyweight.cpp
129 lines (99 loc) · 3.87 KB
/
Flyweight.cpp
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
/*
* Flyweight pattern
*
* Intent: to minimize memory usage by sharing common parts of state between multiple objects
*/
#include <string>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>
#include <unordered_map>
enum class CarClass {
Comfort, Buisness, Premium, Luxury
};
// Shared state
struct CarType {
explicit CarType(std::string model = "", std::string manufacturer = "", CarClass car_class = CarClass::Comfort,
char ISO_type = 'A', int max_speed = 220)
: model(std::move(model)),
manufacturer(std::move(manufacturer)),
car_class(car_class),
ISO_type(ISO_type),
max_speed(max_speed) {}
std::string model;
std::string manufacturer;
CarClass car_class;
char ISO_type;
int max_speed;
};
// Flyweight stores common parts of objects
class Flyweight {
public:
Flyweight() = default;
explicit Flyweight(CarType car_type)
: _car_type(std::move(car_type)) {}
Flyweight& operator=(const CarType& car_type) {
_car_type = car_type;
return *this;
}
CarType& get_car_type() { return _car_type; }
[[nodiscard]] const CarType& get_car_type() const { return _car_type; }
private:
CarType _car_type;
};
// The Flyweight Factory creates and manages the Flyweight objects
class FlyweightFactory {
public:
FlyweightFactory(std::initializer_list<CarType> types) {
for (auto& i: types) {
_hash_table[hash_car_type(i)] = i;
}
}
// Если такого типа нет, то фабрика создаст его
Flyweight& get_flyweight(const CarType& car_type) { return _hash_table[hash_car_type(car_type)]; }
void print_hash_table_size() const { std::cout << _hash_table.size() << '\n'; }
private:
std::string hash_car_type(const CarType& car_type) const {
return car_type.model + "_" + car_type.manufacturer;
}
std::unordered_map<std::string, Flyweight> _hash_table{};
};
// Unique state
class Car {
public:
Car(std::string owner, Flyweight& flyweight)
: _owner(std::move(owner)),
_flyweight(flyweight) {}
friend std::ostream& operator<<(std::ostream& os, const Car& car) {
return os << "Owner: " << car._owner << '\n'
<< "Info: " << car._flyweight.get_car_type().manufacturer
<< ' ' << car._flyweight.get_car_type().model;
}
protected:
std::string _owner;
// Хранить в каждом объекте машины отдельную структуру для ее типа не оптимально,
// т.к. машин может быть очень много, а кол-во типов ограниченно.
// CarType type;
// Мы сэкономим много памяти если будем просто хранить ссылку на объект, который имеет доступ
// к информации и типе машины.
Flyweight& _flyweight;
};
int main() {
CarType premium{"S-Class", "Mercedes-Benz", CarClass::Premium};
CarType buisness{"E-Class", "Mercedes-Benz", CarClass::Buisness};
CarType comfort{"A-Class", "Mercedes-Benz", CarClass::Comfort};
FlyweightFactory factory{premium, buisness, comfort};
std::vector<Car> cars;
for (int i = 0; i < 100; ++i) {
cars.emplace_back("John", factory.get_flyweight(premium));
cars.emplace_back("Alex", factory.get_flyweight(buisness));
cars.emplace_back("Rick", factory.get_flyweight(comfort));
}
for (auto& i: cars)
std::cout << i << '\n';
// Проверим сколько объектов CarType мы храним на данный момент. Всего было создано
// 3 объекта CarType, хотя кол-во всех машин = 300
factory.print_hash_table_size();
return 0;
}