大话设计模式:第26章 享元模式

第26章:享元模式

享元模式

享元(flyweight)模式:运用共享技术有效地支持大量细粒度的对象。

在这里插入图片描述

Flyweight类:所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。

在这里插入图片描述

ConcreteFlyweight:继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。

在这里插入图片描述

UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但它并不强制共享。

在这里插入图片描述

FlyweightFactory是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

在这里插入图片描述

客户端代码

在这里插入图片描述

结果表示

在这里插入图片描述

内部状态与外部状态

享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

享元模式应用

  1. 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时应该考虑使用享元模式;

  2. 对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

使用享元模式,通过共享对象,极大减少实例总数。如果共享的对象越多,存储节约也就越多,节约量随着共享状态的增多而增大。

例,.NET中字符串string运用了Flyweight模式:

在这里插入图片描述

返回值是True,这两个字符串是相同的实例

享元模式更多的时候是一种底层的设计模式,但现实中也是有应用的。比如说休闲游戏开发中,像围棋、五子棋、跳棋等,它们都有大量的棋子对象,棋子的内部状态应该是颜色,而外部状态应该是棋子的方位坐标。

享元模式示例

任务:多客户网站

在这里插入图片描述

from abc import ABCMeta, abstractmethod
from typing import Text

class User(object):
    """
    用户类
    """
    def __init__(self, name: Text) -> None:
        self.__name = name
        
    @property
    def name(self) -> Text:
        return self.__name
    
class WebSite(metaclass=ABCMeta):
    """
    网站抽象类
    """
    @abstractmethod
    def use(self, user: User) -> None:
        pass
string1 = "网站抽象类"

string2 = "网站抽象类"

string1 == string2
True
class ConcreteWebSite(WebSite):
    """
    具体网站类
    """
    def __init__(self, name: Text) -> None:
        self.__name = name
        
    def use(self, user: User) -> None:
        print("网站分类:" + self.__name, "用户:" + user.name)
class WebSiteFactory(object):
    """
    网站工厂类
    """
    def __init__(self):
        self.__flyweights = {}
        
    def get_web_site_category(self, key: Text) -> WebSite:
        if not self.__flyweights.get(key):
            self.__flyweights[key] = ConcreteWebSite(key)
            
        return self.__flyweights[key]
    
    def get_web_site_count(self) -> int:
        return len(self.__flyweights)
    
# 客户端代码

if __name__ == "__main__":
    
    f = WebSiteFactory()
    
    fx = f.get_web_site_category("产品展示")
    fx.use(User("小菜"))
    
    fy = f.get_web_site_category("产品展示")
    fy.use(User("大鸟"))
    
    fz = f.get_web_site_category("产品展示")
    fz.use(User("娇娇"))
    
    fl = f.get_web_site_category("博客")
    fl.use(User("老顽童"))
    
    fm = f.get_web_site_category("博客")
    fm.use(User("桃谷六仙"))
    
    fn = f.get_web_site_category("博客")
    fn.use(User("南海鳄神"))
    
    print("得到网站分类总数为%d" % f.get_web_site_count())


网站分类:产品展示 用户:小菜
网站分类:产品展示 用户:大鸟
网站分类:产品展示 用户:娇娇
网站分类:博客 用户:老顽童
网站分类:博客 用户:桃谷六仙
网站分类:博客 用户:南海鳄神
得到网站分类总数为2

猜你喜欢

转载自blog.csdn.net/zhaoyin214/article/details/106048045