享元法Python设计模式
Flyweight方法是一种结构设计模式,专注于最小化程序在运行时所需的对象数量。基本上,它创建了一个由多个上下文共享的享元对象。它以您无法区分对象和享元对象的方式创建。享元对象的一个重要特征是它们是不可变的。这意味着它们一旦构建就无法修改。
为了在Python中实现享元方法,我们使用Dictionary存储对已创建对象的引用,每个对象都与一个键相关联。
为什么我们要关心程序中的对象数量?
- 更少的对象减少了内存使用,它设法让我们远离与内存相关的错误
- 虽然在Python中创建对象确实很快,但我们仍然可以通过共享对象来减少程序的执行时间。
不使用享元法的问题
想象一下,您是一位非常喜欢赛车游戏的游戏开发者,也想为您和您的朋友开发一款赛车游戏。作为一个完美的游戏开发者,您创建了一个并开始享受游戏。然后你把游戏也发给了你的朋友,但他不太喜欢游戏,因为游戏每隔几分钟就会崩溃。
但为什么? (如果您认为自己是专业游戏开发者,请猜猜原因) 。经过几个小时的调试,您发现问题是您朋友的系统内存不足。与您朋友的系统相比,您的系统功能强大得多,这就是为什么游戏在您的系统上运行顺畅,但在您朋友的系统上却运行不畅的原因。
使用享元法的解决方案
那么,作为开发人员,您将如何提高性能呢? (当然!不打算升级 RAM) 。实际问题与汽车对象有关,因为每辆汽车都由单独的对象表示,其中包含与其颜色、大小、座位、最大速度等相关的大量数据。每当你的 RAM 得到填充并且无法添加当前需要的更多新对象,您的游戏会崩溃。为了避免在应用程序中出现这种情况,开发人员的首要职责是使用享元方法,它允许您通过共享对象的公共部分将更多对象放入可用的 RAM 量。
以下代码是使用享元方法编写的
Python3
class ComplexCars(object):
"""Separate class for Complex Cars"""
def __init__(self):
pass
def cars(self, car_name):
return "ComplexPattern[% s]" % (car_name)
class CarFamilies(object):
"""dictionary to store ids of the car"""
car_family = {}
def __new__(cls, name, car_family_id):
try:
id = cls.car_family[car_family_id]
except KeyError:
id = object.__new__(cls)
cls.car_family[car_family_id] = id
return id
def set_car_info(self, car_info):
"""set the car information"""
cg = ComplexCars()
self.car_info = cg.cars(car_info)
def get_car_info(self):
"""return the car information"""
return (self.car_info)
if __name__ == '__main__':
car_data = (('a', 1, 'Audi'), ('a', 2, 'Ferrari'), ('b', 1, 'Audi'))
car_family_objects = []
for i in car_data:
obj = CarFamilies(i[0], i[1])
obj.set_car_info(i[2])
car_family_objects.append(obj)
"""similar id's says that they are same objects """
for i in car_family_objects:
print("id = " + str(id(i)))
print(i.get_car_info())
输出
id = 58598800
ComplexPattern[Audi]
id = 58598832
ComplexPattern[Ferrari]
id = 58598800
ComplexPattern[Audi]
类图
下面是享元方法的类图
好处
- 减少 RAM 的使用:当我们的应用程序中有很多类似的对象时,最好使用Flyweight 方法以节省大量 RAM 空间
- 改进的数据缓存:当客户端或用户需要高响应时间时,总是首选使用享元方法,因为它有助于改进数据缓存。
- 提高性能:它最终会导致性能提高,因为我们使用的重物数量更少。
缺点
- 打破封装:每当我们试图将状态移动到对象之外时,我们都会打破封装,并且可能会变得比将状态保持在对象内部效率低。
- 难以处理:享元方法的使用取决于我们使用的语言,易于在Python、 Java等语言中使用,其中所有对象变量都是引用,但通常在 C、C++ 等语言中使用,其中对象可以作为局部变量分配在由于程序员的操作,堆栈和销毁。
- 复杂的代码:使用享元方法总是会增加代码的复杂性,以便新开发人员理解。
适用性
- 减少对象的数量:一般来说,当我们的应用程序有很多重量级的对象时,会使用享元方法,为了解决这个问题,我们使用享元方法来摆脱不必要的内存消耗。
- 对象独立应用程序:当我们的应用程序如果独立于对象创建时,那么我们可以利用这种方法来节省大量的机器空间。
- 项目成本降低:当需要在空间和时间复杂度方面降低项目成本时,总是首选使用享元法。
进一步阅读Java中的享元方法