淺談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