设计模式-享元模式
也叫轻量级模式, 轻量模式.
问题描述
属于概念比较好理解的模式. 核心思想就是把高内存占用的只读资源共享, 使其能够在多个位置进行重用.
在不重用的情况下, 每个元素独占一个图片资源, 当重复元素变多就会由于系统资源不足而崩溃.
最常见的属于各类App中的图片素材, 比如按钮底图, 占位符图片. 比较形象的就是扫雷游戏里那一屏幕密密麻麻的方块图片.
简单的python实现
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
from pathlib import Path
from enum import Enum
import tracemalloc
class Point:
def __init__(self, x, y, icon):
self.x = x
self.y = y
self.icon = icon
def draw(self):
print(f">> draw point at: ({self.x},{self.y}) with image:{self.icon}")
class IconType(Enum):
RED = 1
GREEN = 2
BLUE = 3
class PointIcon:
def __init__(self, icon_type, path):
self.icon_type = icon_type
if path:
self.icon = Path(path).read_bytes()
class IconFactory:
__singleton = None
def __init__(self):
self.__icons = {}
IconFactory.__singleton = self
@staticmethod
def instance():
if IconFactory.__singleton is None:
IconFactory.__singleton = IconFactory()
return IconFactory.__singleton
def get_icon(self, icon_type, path):
# key = f"icon-type-{icon_type.name}-{icon_type.__hash__()}"
if icon_type in self.__icons:
return self.__icons[icon_type]
self.__icons[icon_type] = Path(path).read_bytes()
if __name__ == "__main__":
def test_for_100_points():
# pathlib.py:1051: size=8941 KiB, count=100, average=89.4 KiB
# flyweight_pattern.py:44: size=24.8 KiB, count=401, average=63 B
# pathlib.py:508: size=48 B, count=1, average=48 B
tracemalloc.start()
points = [Point(i, i, PointIcon(IconType.RED, "temp.jpg"))
for i in range(0, 100)]
snapshot = tracemalloc.take_snapshot()
stats = snapshot.statistics('lineno')
for stat in stats:
result = str(stat).rsplit('/', 1)[-1]
print(result)
tracemalloc.stop()
def test_for_100_points_with_flyweight():
tracemalloc.start()
icon = IconFactory.instance().get_icon(IconType.RED, "temp.jpg")
points = [Point(i, i, icon) for i in range(0, 100)]
snapshot = tracemalloc.take_snapshot()
stats = snapshot.statistics('lineno')
for stat in stats:
result = str(stat).rsplit('/', 1)[-1]
print(result)
tracemalloc.stop()
test_for_100_points()
print('---')
test_for_100_points_with_flyweight()
最终输出结果:
1
2
3
4
5
6
7
8
9
pathlib.py:1051: size=8941 KiB, count=100, average=89.4 KiB
flyweight_pattern.py:71: size=24.8 KiB, count=401, average=63 B
flyweight_pattern.py:37: size=48 B, count=1, average=48 B
pathlib.py:508: size=48 B, count=1, average=48 B
---
pathlib.py:1051: size=89.4 KiB, count=1, average=89.4 KiB
flyweight_pattern.py:87: size=10.2 KiB, count=201, average=52 B
flyweight_pattern.py:51: size=320 B, count=2, average=160 B
flyweight_pattern.py:60: size=160 B, count=1, average=160 B
本文由作者按照 CC BY 4.0 进行授权