1. 程式人生 > >大話設計模式-享元模式

大話設計模式-享元模式

享元模式

運營共享技術有效地支援大量細粒度的物件。

享元模式的原理

享元模式可以避免大量非常相似類的開銷。在程式設計中,有時需要生成大量細粒度的類的例項來表示資料。

如果能發現這些例項除了幾個引數外基本都是相通的,有時就能夠大幅地減少需要例項化的類的數量。

如果能把那些引數移到類的例項的外面,在方法呼叫時將他們傳遞進來,就可以通過共享大幅地減少單個例項的數目。

我的理解是原來一個物件的例項,它的欄位和屬性佔用100KB,那麼100個物件就是佔用了100*100KB記憶體,現在把不變的提煉出來共享,比如欄位和屬性中由50KB是不變的,那100個物件就是佔用了100*50KB(變的)+50KB(不變的)的記憶體。

佔用記憶體=外部資訊大小*外部資訊例項數量+內部資訊大小*內部資訊例項數量

維護一個鍵值對,外部資訊的某個欄位作為鍵,內部資訊例項作為值,這樣就做到了共享內部資訊。

 

享元模式的使用時機

如果一個應用程式使用了大量的物件,而大量的物件造成了很大的儲存開銷。

物件的大多數狀態是外部狀態,如果刪除物件的外部狀態,那麼可以用相對較少的共享物件取代很多組物件。

 


 

 

享元模式結構演示

使用者

public class User
{
    public string Name { get; private set; }
    public User(string name) => Name = name;
}

網站抽象

abstract class WebSite
{
    public abstract void Use(User user);
}

具體網站

class ConcreteWebsite : WebSite
{
    private string name = "";
    public ConcreteWebsite(String name) => this.name = name;
    public override void Use(User user) => Console.WriteLine($"網站分類:{name} 使用者:{user.Name}
"); }

網站工廠

class WebSiteFactory
{
    Hashtable flyweights = new Hashtable();
    public WebSite GetWebSiteCategory(string key)
    {
        if (!flyweights.ContainsKey(key))
            flyweights.Add(key,new ConcreteWebsite(key));
        return ((WebSite)flyweights[key]);
    }
    public int GetWebsiteCount() => flyweights.Count;
}

測試結果

//網站工廠
WebSiteFactory f = new WebSiteFactory();
//宣告兩個論壇
WebSite fx = f.GetWebSiteCategory("論壇");
fx.Use(new User("路人甲"));
WebSite fy = f.GetWebSiteCategory("論壇");
fy.Use(new User("路人乙"));
//宣告兩個部落格
WebSite fi = f.GetWebSiteCategory("部落格");
fi.Use(new User("路人A"));
WebSite fj = f.GetWebSiteCategory("部落格");
fj.Use(new User("路人B"));
//列印網站種類數量
Console.WriteLine($"網站的種類數量為:{f.GetWebsiteCount()}");
//測試結果
網站分類:論壇 使用者:路人甲
網站分類:論壇 使用者:路人乙
網站分類:部落格 使用者:路人A
網站分類:部落格 使用者:路人B
網站的種類數量為:2