享元模式

简介

享元模式,字面上的意思是分享元始数据,看起来和原型模式好像有些类似。但是实际上两者是不相同的。

原型模式是在已有的基础上进行深拷贝,生成一个全新的对象,对于这个全新的对象,我们可以随意修改。

享元模式则不然,享元模式对于同一种类型的实例,只会生成一个实例对象,区别只是实例对像的属性会有所改变。

举个例子:游戏中有很多树木场景,如果为每棵树都生成一个实例对象,那么一个地图中则需要生成成百上千个树实例,这严重的增加了系统的消耗。

因此,我们希望能将重复类型的树实例对象进行复用。


正文

实现享元模式的关键在于,要判断什么时候可以复用已有的实例对象,什么时候需要创建一个新的实例对象。

下面我们用一个例子来演示一下,如何判断是否生成新的实例。

import random


class Tree:
    pool = {}
    def __new__(cls,tree_type,age,*args,**kwarg):
        obj = cls.pool.get(tree_type,None)
        if not obj:
            new_obj = super().__new__(cls,*args,**kwarg)
            cls.pool[tree_type] = new_obj
            return new_obj
        else:
            return obj

    def __init__(self,*args,**kwarg):
        for k, v in kwarg.items():
            self.__setattr__(k,v)
            
        

    def display(self):
        print('the tree age is {}'.format(self.age))



for i in range(3):
    t = Tree(tree_type='apple',age=random.randrange(1,100))
    print(id(t),t)
    t.display()

for i in range(3):
    t = Tree(tree_type='pear',age=random.randrange(1,100))
    print(id(t),t)
    t.display()

从例子中,我们可以很明显的看出,通过pool池子的管理来决定是否需要生成新的实例对象。对于已经生成过的实例对象,我们只需要在初始化的时候赋予不同的值,便可以进行区分。

因此,我们需要重写new方法,从而达到自主控制实例生成的目的。


总结

大家应该还记得,在之前的模式中,也有一个模式需要重写new方法,从而达到全局只有一个实例的目的——单例模式。

享元模式和单例模式的构成有些类似,区别则是在于,单例模式下,所有类型只能有一个实例,但是享元模式是对于相同类型的实例只能有一个,不同的类型使用不同的实例。

因此享元模式在存在下列常见的时候,是比较适合使用的:

  • 应用需要使用大量的对象
  • 对象太多,存储/渲染它们的代价太大。一旦移除对象中的可变状态(因为在需要之时,应该由客户端代码显示地传递给享元),多组不同的对象可被相对更少的共享对象所替代。
  • 对象ID对于应用不重要。对象共享会造成ID比较的失败,所以不能依赖对象ID(那些在客户端代码看来不同的对象,最终具有相同的ID)。(在例子中我们可以发现,后面的的初始化将前面的覆盖掉了)
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值