Python设计模式:享元模式和单例模式

设计模式八:享元模式和单例模式

什么是享元模式

享元模式是一个用于优化的设计模式,通过为相似对象引入数据共存来最小化内存使用,提升性能。
一个享元就是一个包含状态独立的不可变数据的对象,依赖状态的可变数据不是享元的一部分,每个对象的这种信息不同,无法共享。
享元是一种特定于面向对象编程优化的设计模式,关注的是共享对象数据。

使用场景

应用需要使用大量的对象。
对象太多,存储/渲染的代价太大。
对象ID对于应用不重要。

典型案例

FPS游戏,玩家共享一些状态,比如外在表现和行为,比如跳起低头等行为可以创建一个享元包含所有共同数据,当然也有可变数据,但这些数据不能是享元的一部分,比如当前位置 枪支等。

补充知识

一个对象的实例化过程是先执行类的__new__方法,再调调用__init__方法。
享元模式和单例模式都是在__new__方法中进行实现。

实例代码

from enum import Enum

PeopleType = Enum('People','Chinese American')

class People:
    #对象池,所有实例共享的一个变量
    pool = dict()

    def __new__(cls,types):
        #当客户端创建一个实例时,以类型传入
        #检查是否创建过相同种类的人类,
        #如果有,则返回之前创建的对象,反之将新的种类添加到池中,并返回相应的新对象
        obj = cls.pool.get(types,None)
        if not obj:
            obj = object.__new__(cls)
            cls.pool[types] = obj
            obj.types = types
        return obj
    #渲染方法,需要用户端代码显示传递
    def render(self,name,age):
        print('render a people of {} and name is {} age {}'.format(self.types,name,age))

def Flyweightmain():
    people1 = People(PeopleType.Chinese)
    people1.render('zhang san',18)
    people2 = People(PeopleType.Chinese)
    people2.render('li si',20)
    people3 = People(PeopleType.American)
    people3.render('Arthur',28)
    #由于人类1和人类2是同人种,所以应该id是一样的
    print('people1 id {} == people2 id {}?  {}'.format(id(people1),id(people2),id(people1)==id(people2)))
    #人类1和人类3是不同人种,所以id是不一样的
    print('people1 id {} == people3 id {}?  {}'.format(id(people1),id(people3),id(people1)==id(people3)))
if __name__ == "__main__":
    Flyweightmain()

单例模式

确保某一个类只有一个实例存在,希望整个系统中,某个类只出现一个实施。
同样有最小化内存使用,提升性能的效果。

典型案例

读取配置文件的类。一个大型的系统中,在读取配置文件时,如果过多的创建读取配置文件的类的话,资源会被浪费。

单例模式和享元模式的区别

享元模式可以再次创建对象,也可以取缓存对象。
单例模式则是严格控制单个进程中的一个实例对象。

实例代码

#单例模式需要threading模块
import threading
class Singleton:
    #加锁,防止多线程获取对象时创建过多实例
    _instance_lock = threading.Lock()

    def __init__(self,*args,**kwargs):
        pass

    def __new__(cls,*args,**kwargs):
        #判断是否存在实例,如果存在,返回实例,如果不存在就创建
        if not hasattr(cls,'_instance'):
            with Singleton._instance_lock:
                if not hasattr(cls,'_instance'):
                    Singleton._instance = super().__new__(cls)
        return Singleton._instance

def Singletonmain():
    obj1 = Singleton()
    obj2 = Singleton()
    print(obj1,obj2)
if __name__ == "__main__":
    Singletonmain()

你可能感兴趣的:(设计模式,python,设计模式)