1. 程式人生 > >淺談Java設計模式——享元模式(Flyweight)

淺談Java設計模式——享元模式(Flyweight)

一、概述

        運用共享技術有效地支援大量細粒度的物件。在一個系統中物件會使得記憶體佔用過多,特別是那些大量重複的物件,這就是對系統資源的極大浪費。享元模式對物件的重用提供了一種解決方案,它使用共享技術對相同或者相似物件實現重用。享元模式就是執行共享技術有效地支援大量細粒度物件的複用。系統使用少量物件,而且這些都比較相似,狀態變化小,可以實現物件的多次複用。這裡有一點要注意:享元模式要求能夠共享的物件必須是細粒度物件。享元模式通過共享技術使得系統中的物件個數大大減少了,同時享元模式使用了內部狀態和外部狀態,同時外部狀態相對獨立,不會影響到內部狀態,所以享元模式能夠使得享元物件在不同的環境下被共享。同時正是分為了內部狀態和外部狀態,享元模式會使得系統變得更加複雜,同時也會導致讀取外部狀態所消耗的時間過長。

二、使用場景

1.一個應用程式使用了大量的物件。 

2.完全由於使用大量的物件,造成很大的儲存開銷。 

3.物件的大多數狀態都可變為外部狀態。 

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

5.應用程式不依賴於物件標識。由於Flyweight物件可以被共享,對於概念上明顯有別的物件,標識測試將返回真值

三、參與者

1.Flyweight 描述一個介面,通過這個介面flyweight可以接受並作用於外部狀態。 

2.ConcreteFlyweight 實現Flyweight介面,併為內部狀態(如果有的話)增加儲存空間。 ConcreteFlyweight物件必須是可共享的。它所存                                    儲的狀態必須是內部的;即,它必須獨立於ConcreteFlyweight物件的場景。

3.UnsharedConcreteFlyweight 並非所有的Flyweight子類都需要被共享。Flyweight介面使共享成為可能,但它並不強制共享。 在                                                                  Flyweight物件結構的某些層次,UnsharedConcreteFlyweight物件通常將ConcreteFlyweight物件作為子節                                                    點。

4.FlyweightFactory 建立並管理flyweight物件。 確保合理地共享flyweight。當用戶請求一個flyweight時,FlyweightFactory物件提供一個已                                 建立的例項或者建立一個(如果不存在的話)。

四、類圖

五、示例程式碼

1.Bean

/**
 * Bean
 * @author zhipeng_Tong
 */
public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

2.Flyweight

/**
 * Flyweight介面: WebSite
 * @author zhipeng_Tong
 */
public abstract class WebSite {
    public abstract void use(User user);
}

3.ConcreteFlyweight

/**
 * ConcreteFlyweight
 * @author zhipeng_Tong
 */
public class ConcreteWebSite extends WebSite {
    private String name;

    public ConcreteWebSite(String name) {
        this.name = name;
    }

    @Override
    public void use(User user) {
        System.out.println(String.format("網站分類:%s, 使用者:%s", name, user.getName()));
    }
}

4.UnsharedConcreteFlyweight 暫時不定義

5.FlyweightFactory

/**
 * FlywightFactory
 * @author zhipeng_Tong
 */
public class WebSiteFactory {
    private HashMap<String, WebSite> map = new HashMap<>();

    public WebSite getWebSiteCategory(String key) {
        WebSite webSite;
        if ((webSite = map.get(key)) == null)
            map.put(key, (webSite = new ConcreteWebSite(key)));

        return webSite;
    }

    public int getWebSiteCount() {
        return map.size();
    }
}

6.測試程式碼

public class Client {
    public static void main(String[] args) {
        WebSiteFactory factory = new WebSiteFactory();

        WebSite fx = factory.getWebSiteCategory("產品展示");
        fx.use(new User("小明"));

        WebSite fy = factory.getWebSiteCategory("產品展示");
        fx.use(new User("大明"));

        WebSite fl = factory.getWebSiteCategory("部落格");
        fx.use(new User("哆啦A夢"));

        System.out.println(String.format("網站總數:%s", factory.getWebSiteCount()));
    }
}

執行結果

網站分類:產品展示, 使用者:小明
網站分類:產品展示, 使用者:大明
網站分類:產品展示, 使用者:哆啦A夢
網站總數:2