本文源碼:GitHub·點這裏 || GitEE·點這裏java
應用代碼git
public class C01_InScene { public static void main(String[] args) { String c0 = "cicada" ; String c1 = "cicada" ; System.out.println(c0 == c1); // true } }
String類型就是使用享元模式。String對象是final類型,對象一旦建立就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝,其中c0和c1就是一個字符串常量。結果爲:true,說明c0和c1兩個引用都指向了常量池中的同一個字符串常量"cicada"。這樣的設計避免了在建立N多相同對象時所產生的沒必要要的大量的資源消耗。github
享元模式是對象的結構模式。享元模式以共享的方式高效地支持大量的細粒度對象。經常使用於系統底層開發,解決系統的性能問題。像數據庫鏈接池,裏面都是建立好的鏈接對象,在這些鏈接對象中有須要的則直接拿來用,避免從新建立。數據庫
給出一個抽象接口,以規定具體享元角色要實現的方法。緩存
實現抽象享元角色所規定出的接口。若是有內部狀態的話,必須爲內部狀態提供存儲能力。ide
負責建立和管理享元角色。必須保證享元對象能夠被系統選擇性共享。當一個客戶端對象調用一個享元對象的時候,享元工廠角色會檢查系統中是否已經有一個符合要求的享元對象。若是已經存在,直接返回該對象;若是系統中沒有該享元對象,享元工廠角色就應當建立該享元對象。源碼分析
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"); // 調用了三次工廠方法,只建立了兩個對象 factory.poolInfo(); } } /** * 抽象享元角色類 */ interface Flyweight { void printState (String state); } /** * 具體享元角色類 */ class ConcreteFlyweight implements Flyweight { private Character innerState = null; public ConcreteFlyweight (Character state){ this.innerState = state; } @Override public void printState(String state) { System.out.println("內部狀態:" + this.innerState); System.out.println("外部狀態:" + state); } } /** * 享元工廠角色類 */ class FlyweightFactory { // 模擬數據池 private Map<Character,Flyweight> pool = new HashMap<>(); public Flyweight factoryMethod (Character state){ //先從緩存中查找對象 Flyweight fly = pool.get(state); if(fly == null){ fly = new ConcreteFlyweight(state); pool.put(state, fly); } return fly; } public void poolInfo (){ System.out.println("數據池:"+pool); } }
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); } }
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
這裏valueOf方法的意思就是,若是傳入的數據在 (-128) 到 (127) 之間,則從緩存中直接返回,不然建立一個新的Integer對象。性能
享元模式可以解決重複對象的內存浪費的問題,當系統中有大量類似對象,須要緩衝池時。不需一直建立新對象,能夠從緩衝池裏拿。這樣能夠下降系統內存,同時提升效率。經典的應用場景就是池技術,String常量池、數據庫鏈接池、緩衝池等等都是享元模式的應用,享元模式是池技術的重要實現方式。享元模式使得系統更加複雜。爲了使對象能夠共享,須要時刻管理對象的狀態變化,這使得程序的邏輯變得複雜。測試
GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent