大話設計模式:第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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章