享元模式 #
介绍 #
享元模式通过为相似对象引入数据共享来最小化内存使用,提升性能,一个享元就是一个包含状态的独立的不可变数据的共享对象,依赖状态的可变数据不应是享元的一部分,因为每个对象的这种信息不相同,无法共享,如果享元需要非固有数据应该由客户端代码显示提供。
例如我们正在设计一个性能为关键的游戏,例如第一人称设计游戏(FPS),在FPS游戏中,玩家(士兵)共享一些状态,如外在的表现和行为。例如在 CS 游戏中,同一团队的所有士兵看起来都是一样的,所有的士兵都有一些共同 的动作,比如,低头,跳跃等,这意味着我们可以创建一个享元来包含所有的共同数据,当然,士兵也有许多因人而异的数据,这些数据不是享元的一部分,比如,枪支/健康状况和地理位置等。
应用场景 #
享元旨在优化性能和内存的使用。所有的嵌入式系统(如手机,平板,游戏终端和微控制器等)还有和性能相关的应用,如游戏,3D图形处理和实时系统等,都能从其中获益。
享元模式的使用条件:
- 应用需要使用大量的对象
- 对象太多,存储/渲染它们的代价太大,一旦移除对象中的可变形态,多组不同的对象可以被相对更少的共享对象所替代。
- 对象的ID对于应用不重要,对象共享改会造成ID的比较失败,所以不能依赖对象的ID。
关于memoization与享元模式之间的区别 #
memoization是一种优化技术,使用一个缓存来避免重复计算已经在前期步骤中计算好的结果,memoization并不是只能应用于某种特定的编程方式,还可以应用于方法和简单的函数。享元则是一种特定于面向对象编程优化的审计模式,享元关注的是共享的诗句。
享元的实现 #
在Python中,享元可以以多种方式实现
代码示例https://github.com/lanms/Python_design_pattern/blob/master/07-share_pattern.py
def __new__(cls, tree_type):
obj = cls.pool.get(tree_type, None)
if not obj:
obj = object.__new__(cls)
cls.pool[tree_type] = obj
obj.tree_type = tree_type
return obj
# pool 是一个类属性,使用 __new__ 把 Tree 变成一个元类,元类支持自引用,cls 引用的是 Tree 类,
# 当客户端需要创建一个 Tree实例时,会以 Tree_type 参数传递树的种类,
# 树的种类用于检查是否创建过相同的树,如果已经创建过,则返回之前创建的对象,
# 否则,将这种新的树种添加到池中,并创建新的对象
一句话总结 #
享元模式就是通过避免重复创建大量的已有的实列来优化程序的结构和性能,Python中可以使用元类来创建,类似于单例模式