例子應用:
比如說一個文本系統,每個字母定一個對象,那么大小寫字母一共就是52個,那么就要定義52個對象。如果有一個1M的文本,那么字母是何其的多,如果每個字母都定義一個對象那么內存早就爆了。那么如果要是每個字母都共享一個對象,那么就大大節約了資源。
在Java語言中,String類型就是使用了享元模式。String對象是final類型,對象一旦創建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝。String a="abc",其中"abc"就是一個字符串常量。
數據庫連接池,線程池等即是用享元模式的應用。
什么是享元模式
大量細粒度對象共享復用。復用我們內存中已存在的對象,降低系統創建對象實例的性能消耗。
享元模式:“享”就是分享之意,指一物被眾人共享,而這也正是該模式的終旨所在。
享元模式有點類似于單例模式,都是只生成一個對象來被共享使用。這里有個問題,那就是對共享對象的修改,為了避免出現這種情況,我們將這些對象的公共部分,或者說是不變化的部分抽取出來形成一個對象。這個對象就可以避免到修改的問題。
主要解決
在有大量對象時,有可能會造成內存溢出,我們把其中共同的部分抽象出來,如果有相同的業務請求,直接返回在內存中已有的對象,避免重新創建。
何時使用
1、系統中有大量對象。
2、這些對象消耗大量內存。
3、需要緩沖池的場景。
4、這些對象的狀態大部分可以外部化。
5、這些對象可以按照內蘊狀態分為很多組,當把外蘊對象從對象中剔除出來時,每一組對象都可以用一個對象來代替。
6、系統不依賴于這些對象身份,這些對象是不可分辨的。
7、當我們系統中某個對象類型的實例較多的情況,并且要求這些實例進行分類后,發現真正有區別的分類很少的情況。
如何解決
用唯一標識碼判斷,如果在內存中有,則返回這個唯一標識碼所標識的對象。
關鍵代碼
用 HashMap 存儲這些對象。
優點
大大減少對象的創建,節約內存空間,降低系統的內存,提高系統的性能。
缺點
提高了系統的復雜度,需要分離出外部狀態和內部狀態,而且外部狀態具有固有化的性質,不應該隨著內部狀態的變化而變化,否則會造成系統的混亂。
享元模式一般是給出本地內存資源節省的一個方案,并不適合互聯網上的分布式應用的情況,不過享元模式對于排他性的要求資源的控制,是個不錯的選擇的。
注意事項:
1、注意劃分外部狀態和內部狀態,否則可能會引起線程安全問題。
2、這些類必須有一個工廠對象加以控制。
內部狀態、外部狀態。
內部狀態:在享元對象內部不隨外界環境改變而改變的共享部分。
外部狀態:隨著環境的改變而改變,不能夠共享的狀態就是外部狀態。
內部狀態存儲于享元對象內部,而外部狀態則應該由客戶端來考慮。
享元工廠類
享元模式的核心在于享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,用戶需要對象時,首先從享元池中獲取,如果享元池中不存在,則創建一個新的享元對象返回給用戶,并在享元池中保存該新增對象。
角色
抽象享元:一個接口或抽象類;
具體享元:內部狀態為其成員屬性,其實例為享元對象,可以共享;
享元工廠:生產享元對象,將具體享元對象存儲在一個享元池中,享元池一般設計為一個存儲“鍵值對”的集合;
客戶端:使用享元對象
http://www.cnblogs.com/V1haoge/p/6542449.html
http://blog.csdn.net/jason0539/article/details/22908915
http://www.runoob.com/design-pattern/flyweight-pattern.html
http://www.cnblogs.com/hegezhou_hot/archive/2010/12/12/1903728.html