一、说明
享元模式是一种结构型设计模式,它摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。
(一) 解决问题
旨在减少大量相似对象创建时的内存开销
(二) 使用场景
- 大量相似对象的创建且没有足够的内存容量时
- 对象的大部分状态可以外部化:一个对象的大部分状态可以外部化,即可以从外部传入对象的状态,而对象自身只需保存少量的内部状态时
二、结构
- 享元模式只是一种优化。在应用该模式之前,你要确定程序中存在与大量类似对象同时占用内存相关的内存消耗问题,并且确保该问题无法使用其他更好的方式来解决。
- 享元(Flyweight)类包含原始对象中部分能在多个对象中共享的状态。同一享元对象可在许多不同情景中使用。享元中存储的状态被称为“内在状态”。传递给享元方法的状态被称为“外在状态”。
- 情景(Context)类包含原始对象中各不相同的外在状态。情景与享元对象组合在一起就能表示原始对象的全部状态。
- 通常情况下,原始对象的行为会保留在享元类中。因此调用享元方法必须提供部分外在状态作为参数。但你也可将行为移动到情景类中,然后将连入的享元作为单纯的数据对象。
- 客户端(Client)负责计算或存储享元的外在状态。在客户端看来,享元是一种可在运行时进行配置的模板对象,具体的配置方式为向其方法中传入一些情景数据参数。
- 享元工厂(FlyweightFactory)会对已有享元的缓存池进行管理。有了工厂后,客户端就无需直接创建享元,它们只需调用工厂并向其传递目标享元的一些内在状态即可。工厂会根据参数在之前已创建的享元中进行查找,如果找到满足条件的享元就将其返回;如果没有找到就根据参数新建享元。
三、伪代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__doc__ = """
享元模式
例:游戏程序中,相同类型的子弹可以共享同一个对象,从而节省内存资源。
"""
class Bullet:
"""子弹类"""
def __init__(self, bullet_type):
self.bullet_type = bullet_type
def fire(self, speed, position):
print(f"以 {speed} 的速度,向 {position} 发射 {self.bullet_type}")
class BulletFactory:
"""子弹工厂类"""
_bullets = {}
@staticmethod
def get_bullet(bullet_type):
if bullet_type not in BulletFactory._bullets:
bullet = Bullet(bullet_type)
BulletFactory._bullets[bullet_type] = bullet
else:
bullet = BulletFactory._bullets[bullet_type]
return bullet
if __name__ == "__main__":
"""
以 1000 的速度,向 (100, 200) 发射 子弹
以 1500 的速度,向 (150, 250) 发射 子弹
以 2000 的速度,向 (200, 300) 发射 炮弹
True
False
"""
bullet1 = BulletFactory.get_bullet("子弹")
bullet2 = BulletFactory.get_bullet("子弹")
bullet3 = BulletFactory.get_bullet("炮弹")
bullet1.fire(1000, (100, 200))
bullet2.fire(1500, (150, 250))
bullet3.fire(2000, (200, 300))
print(bullet1 is bullet2)
print(bullet1 is bullet3)
四、优缺点
优点
- 减少内存消耗
- 提高性能:减少了对象的创建和销毁次数
缺点
- 可能引入额外的复杂性:在某些情况下,为了实现对象的共享和状态的管理,可能需要引入额外的复杂性,增加了系统的理解和维护难度。
- 对外部状态的管理可能会带来线程安全问题:如果共享对象的外部状态需要被多个线程修改,可能会引入线程安全问题,需要进行额外的处理来保证线程安全。
跳转主页:【Python笔记】设计模式-CSDN博客