Java描述設(shè)計(jì)模式(18):享元模式
本文源碼:[GitHub·點(diǎn)這里] || [GitEE·點(diǎn)這里]
一、使用場(chǎng)景 **應(yīng)用代碼** ```java public class C01_InScene { public static void main(String[] args) { String c0 = "cicada" ; String c1 = "cicada" ; System.out.println(c0 == c1); // true } } ``` > String類(lèi)型就是使用享元模式。String對(duì)象是final類(lèi)型,對(duì)象一旦創(chuàng)建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會(huì)確保一個(gè)字符串常量在常量池中只有一個(gè)拷貝,其中c0和c1就是一個(gè)字符串常量。結(jié)果為:true,說(shuō)明c0和c1兩個(gè)引用都指向了常量池中的同一個(gè)字符串常量"cicada"。
這樣的設(shè)計(jì)避免了在創(chuàng)建N多相同對(duì)象時(shí)所產(chǎn)生的不必要的大量的資源消耗。
二、享元模式
1、基礎(chǔ)簡(jiǎn)介 > 享元模式是對(duì)象的結(jié)構(gòu)模式。享元模式以共享的方式高效地支持大量的細(xì)粒度對(duì)象。常用于系統(tǒng)底層開(kāi)發(fā),解決系統(tǒng)的性能問(wèn)題。像數(shù)據(jù)庫(kù)連接池,里面都是創(chuàng)建好的連接對(duì)象,在這些連接對(duì)象中有需要的則直接拿來(lái)用,避免重新創(chuàng)建。
2、模式圖解
3、核心角色 - 抽象享元角色 > 給出一個(gè)抽象接口,以規(guī)定具體享元角色要實(shí)現(xiàn)的方法。 - 具體享元角色 > 實(shí)現(xiàn)抽象享元角色所規(guī)定出的接口。如果有內(nèi)部狀態(tài)的話,必須為內(nèi)部狀態(tài)提供存儲(chǔ)能力。 - 享元工廠角色 > 負(fù)責(zé)創(chuàng)建和管理享元角色。必須保證享元對(duì)象可以被系統(tǒng)選擇性共享。當(dāng)一個(gè)客戶端對(duì)象調(diào)用一個(gè)享元對(duì)象的時(shí)候,享元工廠角色會(huì)檢查系統(tǒng)中是否已經(jīng)有一個(gè)符合要求的享元對(duì)象。如果已經(jīng)存在,直接返回該對(duì)象;如果系統(tǒng)中沒(méi)有該享元對(duì)象,享元工廠角色就應(yīng)當(dāng)創(chuàng)建該享元對(duì)象。
4、內(nèi)部外部狀態(tài) - 內(nèi)部狀態(tài)指對(duì)象共享出來(lái)的信息,存儲(chǔ)在享元對(duì)象內(nèi)部且不會(huì)隨環(huán)境的改變而改變。 - 外部狀態(tài)指對(duì)象得以依賴的一個(gè)標(biāo)記,可以隨環(huán)境改變而改變的、不可共享的狀態(tài)。
5、源碼實(shí)現(xiàn) ```java public class C02_FlyWeight { public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight fly = factory.factoryMethod('c'); fly.printState("One"); fly = factory.factoryMethod('d'); fly.printState("Two"); fly = factory.factoryMethod('c'); fly.printState("San"); // 調(diào)用了三次工廠方法,只創(chuàng)建了兩個(gè)對(duì)象 factory.poolInfo(); } } /** * 抽象享元角色類(lèi) */ interface Flyweight { void printState (String state); } /** * 具體享元角色類(lèi) */ class ConcreteFlyweight implements Flyweight { private Character innerState = null; public ConcreteFlyweight (Character state){ this.innerState = state; } @Override public void printState(String state) { System.out.println("內(nèi)部狀態(tài):" + this.innerState); System.out.println("外部狀態(tài):" + state); } } /** * 享元工廠角色類(lèi) */ class FlyweightFactory { // 模擬數(shù)據(jù)池 private Map pool = new HashMap<>(); public Flyweight factoryMethod (Character state){ //先從緩存中查找對(duì)象 Flyweight fly = pool.get(state); if(fly == null){ fly = new ConcreteFlyweight(state); pool.put(state, fly); } return fly; } public void poolInfo (){ System.out.println("數(shù)據(jù)池:"+pool); } } ```
三、JDK應(yīng)用場(chǎng)景 - 測(cè)試代碼塊 ```java public class C03_Integer { public static void main(String[] args) { Integer c1 = Integer.valueOf(127),c2 = Integer.valueOf(127) ; Integer c3 = new Integer(127),c4 = new Integer(127) ; boolean flag1 = c1==c2 ,flag2 = c2==c3,flag3 = c3==c4 ; // true;false;false System.out.println(flag1+";"+flag2+";"+flag3); Integer c5 = Integer.valueOf(222),c6=Integer.valueOf(222) ; // false System.out.println(c5==c6); } } ``` - 源碼分析 ```java public static Integer valueOf(int i) { if (i >= IntegerCache.low && i 享元模式能夠解決重復(fù)對(duì)象的內(nèi)存浪費(fèi)的問(wèn)題,當(dāng)系統(tǒng)中有大量相似對(duì)象,需要緩沖池時(shí)。不需一直創(chuàng)建新對(duì)象,可以從緩沖池里拿。這樣可以降低系統(tǒng)內(nèi)存,同時(shí)提高效率。經(jīng)典的應(yīng)用場(chǎng)景就是池技術(shù),String常量池、數(shù)據(jù)庫(kù)連接池、緩沖池等等都是享元模式的應(yīng)用,享元模式是池技術(shù)的重要實(shí)現(xiàn)方式。享元模式使得系統(tǒng)更加復(fù)雜。為了使對(duì)象可以共享,需要時(shí)刻管理對(duì)象的狀態(tài)變化,這使得程序的邏輯變得復(fù)雜。
五、源代碼地址 ``` GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent ```
聲明:免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請(qǐng)發(fā)
送郵件至:operations@xinnet.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)
需注明出處:新網(wǎng)idc知識(shí)百科