Skip to content

Commit 0ad2eea

Browse files
author
htv-manhlx
committed
add flyweight design pattern
1 parent b5f7524 commit 0ad2eea

File tree

5 files changed

+245
-1
lines changed

5 files changed

+245
-1
lines changed

structural-design-pattern/facade/README-VI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Source
22

3-
https://refactoring.guru/design-patterns/decorator
3+
https://refactoring.guru/design-patterns/facede
44

55
## Cốt lõi:
66

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
## Source
2+
3+
https://refactoring.guru/design-patterns/flyweight
4+
5+
## Cốt lõi:
6+
7+
> Decorator là một mẫu thiết kế cấu trúc cho phép bạn đính kèm các hành vi mới vào các đối tượng bằng cách đặt những đối
8+
> tượng này vào bên trong các đối tượng bọc đặc biệt chứa các hành vi.
9+
10+
## Structure
11+
12+
![alt tag](flyweight.png)
13+
14+
Các bước tạo một flyweight
15+
16+
1. Xác định dữ liệu chung: Đầu tiên, xác định những phần dữ liệu hoặc trạng thái mà các đối tượng Flyweight sẽ chia sẻ.
17+
Đây là những thông tin không thay đổi hoặc ít thay đổi trong quá trình thực thi của ứng dụng.
18+
2. Tạo lớp Flyweight: Tạo một lớp Flyweight, đóng vai trò là đối tượng chia sẻ. Lớp này sẽ bao gồm các thuộc tính chứa
19+
thông tin chung và phương thức để truy cập hoặc cập nhật thông tin này.
20+
3. Tạo lớp Flyweight Factory: Tạo một lớp Factory (nếu cần) để quản lý việc tạo và quản lý các đối tượng Flyweight.
21+
Factory sẽ kiểm tra xem một đối tượng Flyweight đã tồn tại chưa trước khi tạo mới nó và chia sẻ đối tượng đã có khi
22+
cần.
23+
3. Tạo các đối tượng Flyweight: Tạo các đối tượng Flyweight bằng cách sử dụng lớp Factory (nếu có) hoặc tạo trực tiếp.
24+
Khi tạo các đối tượng này, hãy đảm bảo chia sẻ thông tin chung thay vì sao chép nó.
25+
4. Sử dụng đối tượng Flyweight: Trong ứng dụng, sử dụng các đối tượng Flyweight khi cần tham chiếu đến thông tin chung
26+
đó. Thay vì tạo mới đối tượng Flyweight mỗi khi cần, bạn sẽ nhận được một thể hiện đã tồn tại hoặc mới được tạo nếu
27+
chưa tồn tại.
28+
5. Quản lý trạng thái phi chia sẻ: Nếu có các trạng thái riêng biệt cho mỗi đối tượng Flyweight, đảm bảo rằng trạng thái
29+
này không được lưu trữ trong đối tượng Flyweight mà phải được quản lý bên ngoài. Trạng thái phi chia sẻ này sẽ được
30+
truyền vào đối tượng Flyweight khi cần.
31+
6. Theo dõi sự thay đổi và tương tác: Theo dõi việc sử dụng và tương tác với các đối tượng Flyweight để đảm bảo tính
32+
nhất quán và an toàn trong ứng dụng.
33+
34+
## Description
35+
36+
### Mục đích
37+
38+
Mục đích chính của Flyweight Design Pattern là giảm thiểu sự sử dụng bộ nhớ hoặc tối ưu hóa hiệu suất bằng cách chia sẻ
39+
tối đa dữ liệu hoặc trạng thái giữa các đối tượng. Pattern này thường được sử dụng trong trường hợp khi có rất nhiều đối
40+
tượng có cùng một phần lớn dữ liệu chung hoặc có thể được chia sẻ. Flyweight giúp tiết kiệm bộ nhớ và tăng hiệu suất
41+
bằng cách sử dụng một số đối tượng chia sẻ thay vì tạo mới một đối tượng riêng lẻ cho mỗi trường hợp.
42+
Dưới đây là một số mục đích cụ thể của Flyweight Design Pattern:
43+
44+
1. **Tiết kiệm bộ nhớ:** Bằng cách chia sẻ thông tin chung giữa các đối tượng, Flyweight giúp giảm sự sử dụng bộ nhớ.
45+
Điều này quan trọng khi bạn có hàng ngàn đối tượng cùng sử dụng một tập dữ liệu lớn.
46+
2. **Tối ưu hóa hiệu suất:** Flyweight giúp cải thiện hiệu suất bằng cách giảm thiểu việc tạo và hủy các đối tượng cùng
47+
loại. Nó giúp giảm tải cho máy chủ hoặc ứng dụng, đặc biệt khi có nhiều yêu cầu xử lý.
48+
3. **Tạo đối tượng bất biến:** Flyweight có thể kết hợp với Flyweight Factory để đảm bảo rằng một đối tượng chỉ được tạo
49+
một lần và sau đó chia sẻ trong toàn bộ ứng dụng. Điều này có thể đảm bảo tính bất biến và an toàn trong ứng dụng.
50+
4. **Tăng tái sử dụng:** Flyweight cho phép bạn tái sử dụng các đối tượng đã có thay vì tạo mới chúng. Điều này giúp
51+
giảm sự phức tạp của mã và tạo điều kiện thuận lợi cho việc bảo trì và mở rộng ứng dụng.
52+
5. **Giảm thiểu tài nguyên hệ thống:** Nếu bạn có một ứng dụng hoặc hệ thống có nhiều đối tượng tương tự, sử dụng
53+
Flyweight có thể giúp giảm thiểu tài nguyên hệ thống và giúp ứng dụng chạy mượt mà hơn.
54+
55+
## Khi nào thì sử dụng flyweight
56+
57+
Flyweight Design Pattern thường được sử dụng trong các tình huống sau khi bạn nhận thấy rằng có nhiều đối tượng có chung
58+
một số lượng lớn dữ liệu chung hoặc trạng thái, và bạn muốn tối ưu hóa việc sử dụng bộ nhớ hoặc hiệu suất bằng cách chia
59+
sẻ thông tin này giữa các đối tượng. Dưới đây là một số tình huống cụ thể khi bạn nên xem xét sử dụng Flyweight:
60+
61+
1. **Sử dụng chung dữ liệu tĩnh:** Khi có một tập dữ liệu tĩnh (không thay đổi) mà nhiều đối tượng sử dụng, ví dụ như
62+
danh sách các biểu tượng hoặc loại sản phẩm, bạn có thể sử dụng Flyweight để chia sẻ dữ liệu này giữa các đối tượng.
63+
2. **Ứng dụng đòi hỏi tối ưu hóa bộ nhớ:** Trong các ứng dụng có số lượng lớn đối tượng, việc tạo một đối tượng riêng lẻ
64+
cho mỗi trường hợp có thể dẫn đến sử dụng bộ nhớ lớn. Sử dụng Flyweight giúp giảm thiểu việc sử dụng bộ nhớ bằng cách
65+
chia sẻ thông tin chung.
66+
3. **Cải thiện hiệu suất:** Khi ứng dụng của bạn đối diện với tình huống yêu cầu tối ưu hóa hiệu suất, như xử lý hàng
67+
ngàn yêu cầu mỗi giây, Flyweight có thể giúp giảm tải cho ứng dụng bằng cách giảm thiểu tạo mới đối tượng và giảm
68+
thiểu overhead.
69+
4. **Tạo đối tượng không thay đổi (immutable):** Flyweight thường kết hợp tốt với việc tạo đối tượng không thay đổi. Nếu
70+
bạn muốn đảm bảo rằng một đối tượng không thay đổi chỉ được tạo một lần và sau đó chia sẻ trong toàn bộ ứng dụng,
71+
Flyweight có thể giúp thực hiện điều này.
72+
5. **Ứng dụng có nhiều trạng thái:** Khi có một số trạng thái chia sẻ giữa các đối tượng, bạn có thể sử dụng Flyweight
73+
để chia sẻ trạng thái này thay vì lưu trữ nó trong từng đối tượng.
74+
6. **Giảm tải cho máy chủ:** Trong ứng dụng máy chủ, ví dụ như máy chủ web hoặc máy chủ trò chơi, Flyweight có thể giúp
75+
giảm tải cho máy chủ bằng cách chia sẻ thông tin chung với nhiều yêu cầu từ khách hàng.
76+
7. **Tối ưu hóa các tài nguyên hệ thống:** Khi bạn muốn giảm thiểu tài nguyên hệ thống mà ứng dụng của bạn sử dụng,
77+
Flyweight có thể là một lựa chọn hữu ích.
78+
79+
## Running
80+
81+
```
82+
python main.py
83+
python example.py
84+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Source
2+
3+
https://refactoring.guru/design-patterns/flyweight
4+
5+
### Important:
6+
7+
> 1. Flyweight is a structural design pattern that lets you fit more objects into the available amount of RAM by sharing
8+
common parts of state between multiple objects instead of keeping all of the data in each object.
9+
> 2. A fine-grained instance used for efficient sharing. Also known as: Cache
10+
11+
## Description
12+
13+
## Structure
14+
15+
![alt tag](flyweight.png)
16+
17+
## How to use
18+
19+
1. Use the Flyweight pattern only when your program must support a huge number of objects which barely fit into available
20+
RAM.
21+
22+
## How to implement
23+
24+
https://refactoring.guru/design-patterns/flyweight#checklist
25+
26+
## Running
27+
28+
```
29+
python main.py
30+
python example.py
31+
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
class TreeType:
2+
def __init__(self, name, color, texture):
3+
self.name = name
4+
self.color = color
5+
self.texture = texture
6+
7+
def draw(self, canvas, x, y):
8+
print(f"TreeType.draw: {self.name} {self.color} {self.texture} {x} {y}")
9+
10+
11+
class TreeFactory:
12+
tree_types = {}
13+
14+
@staticmethod
15+
def get_tree_type(name, color, texture):
16+
if not TreeFactory.tree_types.get(name):
17+
TreeFactory.tree_types[name] = TreeType(name, color, texture)
18+
19+
return TreeFactory.tree_types[name]
20+
21+
22+
class Tree:
23+
def __init__(self, x, y, tree_type):
24+
self.x = x
25+
self.y = y
26+
self.tree_type = tree_type
27+
28+
def draw(self, canvas):
29+
self.tree_type.draw(canvas, self.x, self.y)
30+
31+
32+
class Forest:
33+
def __init__(self):
34+
self.trees = []
35+
36+
def plant_tree(self, x, y, name, color, texture):
37+
tree_type = TreeFactory.get_tree_type(name, color, texture)
38+
tree = Tree(x, y, tree_type)
39+
self.trees.append(tree)
40+
41+
def draw(self, canvas):
42+
for tree in self.trees:
43+
tree.draw(canvas)
44+
45+
46+
if __name__ == "__main__":
47+
forest = Forest()
48+
forest.plant_tree(1, 2, "name", "color", "texture")
49+
forest.draw("canvas")
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""
2+
Source: https://refactoring.guru/design-patterns/flyweight/python/example
3+
"""
4+
import json
5+
6+
7+
class Flyweight:
8+
def __init__(self, shared_state: str) -> None:
9+
self._shared_state = shared_state
10+
11+
def operation(self, unique_state: str) -> None:
12+
s = json.dumps(self._shared_state)
13+
u = json.dumps(unique_state)
14+
print(f"Flyweight: Displaying shared ({s}) and unique ({u}) state.", end="")
15+
16+
17+
class FlyweightFactory:
18+
_flyweights = {}
19+
20+
def __init__(self, initial_flyweights) -> None:
21+
for state in initial_flyweights:
22+
self._flyweights[self.get_key(state)] = Flyweight(state)
23+
24+
def get_key(self, state) -> str:
25+
return "_".join(sorted(state))
26+
27+
def get_flyweight(self, shared_state) -> Flyweight:
28+
key = self.get_key(shared_state)
29+
30+
if not self._flyweights.get(key):
31+
print("FlyweightFactory: Can't find a flyweight, creating new one.")
32+
self._flyweights[key] = Flyweight(shared_state)
33+
else:
34+
print("FlyweightFactory: Reusing existing flyweight.")
35+
36+
return self._flyweights[key]
37+
38+
def list_flyweights(self) -> None:
39+
count = len(self._flyweights)
40+
print(f"FlyweightFactory: I have {count} flyweights:")
41+
print("\n".join(map(str, self._flyweights.keys())), end="")
42+
43+
44+
def add_car_to_police_database(
45+
factory: FlyweightFactory, owner: str, brand: str, model: str, color: str
46+
) -> None:
47+
print("\n\nClient: Adding a car to database.")
48+
flyweight = factory.get_flyweight([brand, model, color])
49+
# The client code either stores or calculates extrinsic state and passes it
50+
# to the flyweight's methods.
51+
flyweight.operation(owner)
52+
53+
54+
if __name__ == "__main__":
55+
"""
56+
The client code usually creates a bunch of pre-populated flyweights in the
57+
initialization stage of the application.
58+
"""
59+
60+
factory = FlyweightFactory([
61+
["Chevrolet", "Camaro2018", "pink"],
62+
["Mercedes Benz", "C300", "black"],
63+
["Mercedes Benz", "C500", "red"],
64+
["BMW", "M5", "red"],
65+
["BMW", "X6", "white"],
66+
])
67+
68+
factory.list_flyweights()
69+
70+
add_car_to_police_database(
71+
factory, "James Doe", "BMW", "M5", "red"
72+
)
73+
74+
add_car_to_police_database(
75+
factory, "James Doe", "BMW", "X1", "red"
76+
)
77+
78+
print("\n")
79+
80+
factory.list_flyweights()

0 commit comments

Comments
 (0)