Skip to content

Commit a8ae091

Browse files
Eder DuranEder Duran
authored andcommitted
Flyweight pattern
1 parent e64c597 commit a8ae091

2 files changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FlyweightFactory: I have 5 flyweights:
2+
BMW_X6_white
3+
Mercedes Benz_C500_red
4+
Mercedes Benz_C300_black
5+
BMW_M5_red
6+
Chevrolet_Camaro2018_pink
7+
8+
Client: Adding a car to database.
9+
FlyweightFactory: Reusing existing flyweight.
10+
Flyweight: Displaying shared ([ BMW , M5 , red ]) and unique ([ CL234IR , James Doe ]) state.
11+
12+
Client: Adding a car to database.
13+
FlyweightFactory: Can't find a flyweight, creating new one.
14+
Flyweight: Displaying shared ([ BMW , X1 , red ]) and unique ([ CL234IR , James Doe ]) state.
15+
16+
FlyweightFactory: I have 6 flyweights:
17+
BMW_X1_red
18+
Mercedes Benz_C300_black
19+
BMW_X6_white
20+
Mercedes Benz_C500_red
21+
BMW_M5_red
22+
Chevrolet_Camaro2018_pink

src/Flyweight/Conceptual/main.cc

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <vector>
4+
#include <unordered_map>
5+
6+
/**
7+
* EN: Flyweight Design Pattern
8+
*
9+
* Intent: Lets you fit more objects into the available amount of RAM by sharing
10+
* common parts of state between multiple objects, instead of keeping all of the
11+
* data in each object.
12+
*
13+
* RU: Паттерн Легковес
14+
*
15+
* Назначение: Позволяет вместить бóльшее количество объектов в отведённую
16+
* оперативную память. Легковес экономит память, разделяя общее состояние
17+
* объектов между собой, вместо хранения одинаковых данных в каждом объекте.
18+
*/
19+
20+
struct SharedState
21+
{
22+
std::string brand_;
23+
std::string model_;
24+
std::string color_;
25+
26+
SharedState(const std::string &brand, const std::string &model, const std::string &color)
27+
: brand_(brand), model_(model), color_(color)
28+
{
29+
}
30+
31+
friend std::ostream &operator<<(std::ostream &os, const SharedState &ss)
32+
{
33+
return os << "[ " << ss.brand_ << " , " << ss.model_ << " , " << ss.color_ << " ]";
34+
}
35+
};
36+
37+
struct UniqueState
38+
{
39+
std::string owner_;
40+
std::string plates_;
41+
42+
UniqueState(const std::string &owner, const std::string &plates)
43+
: owner_(owner), plates_(plates)
44+
{
45+
}
46+
47+
friend std::ostream &operator<<(std::ostream &os, const UniqueState &us)
48+
{
49+
return os << "[ " << us.owner_ << " , " << us.plates_ << " ]";
50+
}
51+
};
52+
53+
/**
54+
* EN: The Flyweight stores a common portion of the state (also called intrinsic
55+
* state) that belongs to multiple real business entities. The Flyweight accepts
56+
* the rest of the state (extrinsic state, unique for each entity) via its
57+
* method parameters.
58+
*
59+
* RU: Легковес хранит общую часть состояния (также называемую внутренним
60+
* состоянием), которая принадлежит нескольким реальным бизнес-объектам.
61+
* Легковес принимает оставшуюся часть состояния (внешнее состояние, уникальное
62+
* для каждого объекта) через его параметры метода.
63+
*/
64+
class Flyweight
65+
{
66+
private:
67+
SharedState *shared_state_;
68+
69+
public:
70+
Flyweight(const SharedState *shared_state) : shared_state_(new SharedState(*shared_state))
71+
{
72+
}
73+
Flyweight(const Flyweight &other) : shared_state_(new SharedState(*other.shared_state_))
74+
{
75+
}
76+
~Flyweight()
77+
{
78+
delete shared_state_;
79+
}
80+
SharedState *shared_state() const
81+
{
82+
return shared_state_;
83+
}
84+
void Operation(const UniqueState &unique_state) const
85+
{
86+
std::cout << "Flyweight: Displaying shared (" << *shared_state_ << ") and unique (" << unique_state << ") state.\n";
87+
}
88+
};
89+
/**
90+
* EN: The Flyweight Factory creates and manages the Flyweight objects. It
91+
* ensures that flyweights are shared correctly. When the client requests a
92+
* flyweight, the factory either returns an existing instance or creates a new
93+
* one, if it doesn't exist yet.
94+
*
95+
* RU: Фабрика Легковесов создает объекты-Легковесы и управляет ими. Она
96+
* обеспечивает правильное разделение легковесов. Когда клиент запрашивает
97+
* легковес, фабрика либо возвращает существующий экземпляр, либо создает новый,
98+
* если он ещё не существует.
99+
*/
100+
class FlyweightFactory
101+
{
102+
/**
103+
* @var Flyweight[]
104+
*/
105+
private:
106+
std::unordered_map<std::string, Flyweight> flyweights_;
107+
/**
108+
* EN: Returns a Flyweight's string hash for a given state.
109+
*
110+
* RU: Возвращает хеш строки Легковеса для данного состояния.
111+
*/
112+
std::string GetKey(const SharedState &ss) const
113+
{
114+
return ss.brand_ + "_" + ss.model_ + "_" + ss.color_;
115+
}
116+
117+
public:
118+
FlyweightFactory(std::initializer_list<SharedState> share_states)
119+
{
120+
for (const SharedState &ss : share_states)
121+
{
122+
this->flyweights_.insert(std::make_pair<std::string, Flyweight>(this->GetKey(ss), Flyweight(&ss)));
123+
}
124+
}
125+
126+
/**
127+
* EN: Returns an existing Flyweight with a given state or creates a new
128+
* one.
129+
*
130+
* RU: Возвращает существующий Легковес с заданным состоянием или создает
131+
* новый.
132+
*/
133+
Flyweight GetFlyweight(const SharedState &shared_state)
134+
{
135+
std::string key = this->GetKey(shared_state);
136+
if (this->flyweights_.find(key) == this->flyweights_.end())
137+
{
138+
std::cout << "FlyweightFactory: Can't find a flyweight, creating new one.\n";
139+
this->flyweights_.insert(std::make_pair(key, Flyweight(&shared_state)));
140+
}
141+
else
142+
{
143+
std::cout << "FlyweightFactory: Reusing existing flyweight.\n";
144+
}
145+
return this->flyweights_.at(key);
146+
}
147+
void ListFlyweights() const
148+
{
149+
size_t count = this->flyweights_.size();
150+
std::cout << "\nFlyweightFactory: I have " << count << " flyweights:\n";
151+
for (std::pair<std::string, Flyweight> pair : this->flyweights_)
152+
{
153+
std::cout << pair.first << "\n";
154+
}
155+
}
156+
};
157+
158+
// ...
159+
void AddCarToPoliceDatabase(
160+
FlyweightFactory &ff, const std::string &plates, const std::string &owner,
161+
const std::string &brand, const std::string &model, const std::string &color)
162+
{
163+
std::cout << "\nClient: Adding a car to database.\n";
164+
const Flyweight &flyweight = ff.GetFlyweight({brand, model, color});
165+
// EN: The client code either stores or calculates extrinsic state and
166+
// passes it to the flyweight's methods.
167+
//
168+
// RU: Клиентский код либо сохраняет, либо вычисляет внешнее состояние и
169+
// передает его методам легковеса.
170+
flyweight.Operation({plates, owner});
171+
}
172+
173+
/**
174+
* EN: The client code usually creates a bunch of pre-populated flyweights in
175+
* the initialization stage of the application.
176+
*
177+
* RU: Клиентский код обычно создает кучу предварительно заполненных легковесов
178+
* на этапе инициализации приложения.
179+
*/
180+
181+
int main()
182+
{
183+
FlyweightFactory *factory = new FlyweightFactory({{"Chevrolet", "Camaro2018", "pink"}, {"Mercedes Benz", "C300", "black"}, {"Mercedes Benz", "C500", "red"}, {"BMW", "M5", "red"}, {"BMW", "X6", "white"}});
184+
factory->ListFlyweights();
185+
186+
AddCarToPoliceDatabase(*factory,
187+
"CL234IR",
188+
"James Doe",
189+
"BMW",
190+
"M5",
191+
"red");
192+
193+
AddCarToPoliceDatabase(*factory,
194+
"CL234IR",
195+
"James Doe",
196+
"BMW",
197+
"X1",
198+
"red");
199+
factory->ListFlyweights();
200+
delete factory;
201+
202+
return 0;
203+
}

0 commit comments

Comments
 (0)