前言
java
秋雨綿綿,週末午後,小區涼亭。
面試
李大爺:"你來了。"編程
我:"我來了。"設計模式
李大爺:"我知道你會來的!"bash
我:"我固然會來,你固然知道,不然一天前你又怎會讓我走?"服務器
我目光重落,再次凝視着他,過了好久,才緩緩道:"如今一天已過去。ide
李大爺:"整整一天。"性能
我:"好長的一天。"測試
李大爺:"好短的一天。"ui
我:"雖然我明知今日必死但我不是那種等死的人。"
李大爺:"如今你的事是否已作完,你的心願已了。"
秋雨依舊綿綿,行人寥寥。
李大爺:"出招吧!"
我:"一天前,我敗在你的手下。"
李大爺淡淡道:"也許你本不應敗的,只惋惜你的人太年輕,棋法卻用老了。"
我:"你借我一天時光,讓我去作我本身想作的事,如今一天已過去,我……"
李大爺道:"你是來送死的。"
我:"不錯,我正是來送死的。"
我:"我既然來了,就已抱定必死之心。"
李大爺道:"你不想再多活一天?"
我突然仰面而笑,道:"大丈夫生於世,若不能下棋贏遍小區大爺,廣場舞浪過廣場大媽,快意恩仇,就算再多活一百年,也是生不如死"。
李大爺打斷了個人話,冷冷道:"你本不是個多話的人,我也不是來跟你說話的,你只求速死?"
我:"是。"
李大爺長長吐出口氣,閉上眼瞪,道:"請!請出手,今天仍是你先走第一步。"
什麼是享元模式
爲了方便理解,咱們先來看一下享元模式的兩種狀態:
內部狀態(Intrinsic State):是存儲在享元對象內部而且不會隨環境改變而改變的狀態,所以內部狀態能夠共享。
外部狀態(Extrinsic State):是隨環境改變而改變的、不能夠共享的狀態。享元對象的外部狀態必須由客戶端保存,並在享元對象被建立以後,在須要使用的時候再傳入到享元對象內部。一個外部狀態與另外一個外部狀態之間是相互獨立的。
如今咱們來看一下享元模式的英文定義:
Flyweight Pattern: Use sharing to support large numbers of fine-grained objects efficiently.
享元模式(Flyweight Pattern):運用共享技術有效地支持大量細粒度對象的複用。系統只使用少許的對象,而這些對象都很類似,狀態變化很小,能夠實現對象的屢次複用。因爲享元模式要求可以共享的對象必須是細粒度對象,所以它又稱爲輕量級模式,它是一種對象結構型模式。
享元模式的四個角色
Flyweight(抽象享元類):接口或抽象類,聲明公共方法,這些方法能夠向外界提供對象的內部狀態,設置外部狀態。
ConcreteFlyweight(具體享元類):實現了抽象享元類,其實例稱爲享元對象。必須是可共享的,須要封裝享元對象的內部狀態;。
UnsharedConcreteFlyweight(非共享具體享元類):非共享的享元實現對象,並非全部的享元對象均可以共享,非共享的享元對象一般是享元對象的組合對象。
FlyweightFactory(享元工廠類):享元工廠,主要用來建立並管理共享的享元對象,並對外提供訪問共享享元的接口。它針對抽象享元類編程,將各類類型的具體享元對象存儲在一個享元池中,享元池通常設計爲一個存儲「鍵值對」的集合(也能夠是其餘類型的集合),能夠結合工廠模式進行設計;當用戶請求一個具體享元對象時,享元工廠提供一個存儲在享元池中已建立的實例或者建立一個新的實例(若是不存在的話),返回新建立的實例並將其存儲在享元池中。
享元模式的UML圖
代碼實例
package com.weiya.mazhichu.designpatterns.flyweight;/** * <p class="detail"> * 功能:抽象享元類 * </p> * * @author Moore * @ClassName Soldier flyweight. * @Version V1.0. * @date 2019.09.03 21:06:52 */public interface SoldierFlyweight { /** * <p class="detail"> * 功能:敵軍出擊方法 * </p> * * @param direction : * @author Moore * @date 2019.09.03 21:06:52 */ public void attack(String direction);}複製代碼
二、編寫具體享元類
package com.weiya.mazhichu.designpatterns.flyweight;/** * <p class="detail"> * 功能:具體享元類 * </p> * * @author Moore * @ClassName Concrete solider flyweight. * @Version V1.0. * @date 2019.09.04 09:45:41 */public class ConcreteSoliderFlyweight implements SoldierFlyweight { // 內部狀態 private String soliderType; public ConcreteSoliderFlyweight(String soliderType) { this.soliderType = soliderType; } @Override public void attack(String direction) { if("normal".equals(soliderType)){ System.out.println("普通兵加入戰場"); } if("super".equals(soliderType)){ System.out.println("超級兵加入戰場"); } System.out.println("出擊方向:"+direction); }}複製代碼
三、編寫享元工廠
package com.weiya.mazhichu.designpatterns.flyweight;import java.util.HashMap;import java.util.Map;/** * <p class="detail"> * 功能:享元工廠 * </p> * * @author Moore * @ClassName Soldier fly weight factory. * @Version V1.0. * @date 2019.09.03 21:06:58 */public class SoldierFlyWeightFactory { //工廠實例 private static SoldierFlyWeightFactory INSTANCE; // 享元池 private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>(); private SoldierFlyWeightFactory(){ SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal"); soldierMap.put("normal",normalSoldier); SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super"); soldierMap.put("super",superSolider); } /** * <p class="detail"> * 功能:獲取工廠實例 * </p> * * @return soldier fly weight factory * @author Moore * @date 2019.09.03 21:07:02 */ public static SoldierFlyWeightFactory getInstance(){ if(INSTANCE == null){ INSTANCE = new SoldierFlyWeightFactory(); return INSTANCE; } return INSTANCE; } /** * <p class="detail"> * 功能:獲取享元對象 * </p> * * @param soliderType : * @return soldier flyweight * @author Moore * @date 2019.09.03 21:07:02 */ public SoldierFlyweight getSolider(String soliderType){ return soldierMap.get(soliderType); } /** * <p class="detail"> * 功能:獲取享元池對象數量 * </p> * * @return int * @author Moore * @date 2019.09.03 21:07:02 */ public int getSoliderSize(){ return soldierMap.size(); }}複製代碼
四、客戶端測試
package com.weiya.mazhichu.designpatterns.flyweight;/** * <p class="detail"> * 功能: * </p> * * @author Moore * @ClassName Honour of kings test. * @Version V1.0. * @date 2019.09.03 21:06:44 */public class HonourOfKingsTest { public static void main(String[] args) { System.out.println("敵軍還有五秒到達戰場!"); SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance(); SoldierFlyweight soldier1 = factory.getSolider("normal"); SoldierFlyweight soldier2 = factory.getSolider("normal"); SoldierFlyweight soldier3 = factory.getSolider("normal"); soldier1.attack("上路"); soldier2.attack("中路"); soldier3.attack("下路"); System.out.println(soldier1 == soldier2); System.out.println(soldier2 == soldier3); System.out.println("--------------------------"); System.out.println("主宰已被擊敗!"); SoldierFlyweight soldier4 = factory.getSolider("super"); SoldierFlyweight soldier5 = factory.getSolider("super"); SoldierFlyweight soldier6 = factory.getSolider("super"); soldier4.attack("上路"); soldier5.attack("中路"); soldier6.attack("下路"); System.out.println("對方法師殘血,被超級兵打死..."); System.out.println(soldier4 == soldier5); System.out.println(soldier5 == soldier6); System.out.println("--------------------------"); System.out.println("該案例一共生成對象:" + factory.getSoliderSize() + "個"); }}複製代碼
查看運行結果:
享元模式擴展
單純享元模式:在單純享元模式中,全部的享元對象都是能夠共享的,即全部抽象享元類的子類均可共享,不存在非共享具體享元類。
複合享元模式:將一些單純享元使用組合模式加以組合,能夠造成複合享元對象,這樣的複合享元對象自己不能共享,可是它們能夠分解成單純享元對象,然後者則能夠共享。(複合的享元對象實現了抽象享元類,它的實例就是非共享的享元實現對象)
package com.weiya.mazhichu.designpatterns.flyweight;import java.util.HashMap;import java.util.Map;/** * <p class="detail"> * 功能: 複合享元角色類(非共享享元實現對象) * </p> * * @author Moore * @ClassName Concrete composite solider flyweight. * @Version V1.0. * @date 2019.09.04 10:56:11 */public class ConcreteCompositeSoliderFlyweight implements SoldierFlyweight { private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>(); /** * <p class="detail"> * 功能: 增長單純享元對象 * </p> * * @param soliderType : * @param flyweight : * @author Moore * @date 2019.09.04 10:56:11 */ public void add(String soliderType,SoldierFlyweight flyweight){ soldierMap.put(soliderType,flyweight); } /** * <p class="detail"> * 功能: flyWeights是單純享元對象的集合,它們具備相同的外部狀態extrinsicState, * 調用的時候使用循環調用單純享元對象的attack方法 * </p> * * @param direction : * @author Moore * @date 2019.09.03 21:06:52 */ @Override public void attack(String direction) { SoldierFlyweight flyweight = null; for(String str : soldierMap.keySet()){ flyweight = soldierMap.get(str); flyweight.attack(direction); } } /** * 移除單純享元對象. * @param soliderType */ private void remove(String soliderType) { soldierMap.remove(soliderType); }}複製代碼
package com.weiya.mazhichu.designpatterns.flyweight;import java.util.HashMap;import java.util.List;import java.util.Map;/** * <p class="detail"> * 功能:享元工廠 * </p> * * @author Moore * @ClassName Soldier fly weight factory. * @Version V1.0. * @date 2019.09.03 21:06:58 */public class SoldierFlyWeightFactory { //工廠實例 private static SoldierFlyWeightFactory INSTANCE; // 享元池 private static Map<String,SoldierFlyweight> soldierMap = new HashMap<String,SoldierFlyweight>(); private SoldierFlyWeightFactory(){ SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal"); soldierMap.put("normal",normalSoldier); SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super"); soldierMap.put("super",superSolider); } /** * <p class="detail"> * 功能:獲取工廠實例 * </p> * * @return soldier fly weight factory * @author Moore * @date 2019.09.03 21:07:02 */ public static SoldierFlyWeightFactory getInstance(){ if(INSTANCE == null){ INSTANCE = new SoldierFlyWeightFactory(); return INSTANCE; } return INSTANCE; } /** * <p class="detail"> * 功能:獲取享元對象(單純享元工廠方法) * </p> * * @param soliderType : * @return soldier flyweight * @author Moore * @date 2019.09.03 21:07:02 */ public SoldierFlyweight getSolider(String soliderType){ return soldierMap.get(soliderType); } /** * <p class="detail"> * 功能:複合享元工廠方法 * </p> * * @param compositeSoliderTypes : * @return soldier flyweight * @author Moore * @date 2019.09.04 11:06:24 */ public SoldierFlyweight getCompositeSolider(List<String> compositeSoliderTypes){ ConcreteCompositeSoliderFlyweight compositeFlyweight = new ConcreteCompositeSoliderFlyweight(); for(String soliderType : compositeSoliderTypes){ compositeFlyweight.add(soliderType,this.getSolider(soliderType)); } return compositeFlyweight; } /** * <p class="detail"> * 功能:獲取享元池對象數量 * </p> * * @return int * @author Moore * @date 2019.09.03 21:07:02 */ public int getSoliderSize(){ return soldierMap.size(); }}複製代碼
package com.weiya.mazhichu.designpatterns.flyweight;import java.util.ArrayList;import java.util.List;/** * <p class="detail"> * 功能: 測試單純享元模式和複合享元模式 * </p> * * @author Moore * @ClassName Flyweight test. * @Version V1.0. * @date 2019.09.04 11:08:51 */public class FlyweightTest { public static void main(String[] args) { SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance(); String soliderType = "normal"; SoldierFlyweight soldierFlyweight1 = factory.getSolider(soliderType); SoldierFlyweight soldierFlyweight2 = factory.getSolider(soliderType); soldierFlyweight1.attack("上路"); soldierFlyweight2.attack("中路"); System.out.println("---------------------------------"); List<String> compositeSoliderType = new ArrayList<String>(); compositeSoliderType.add("normal"); compositeSoliderType.add("super"); compositeSoliderType.add("normal"); compositeSoliderType.add("super"); compositeSoliderType.add("normal"); SoldierFlyweight compositeSoliderFlyeweight1 = factory.getSolider(compositeSoliderType); SoldierFlyweight compositeSoliderFlyeweight2 = factory.getSolider(compositeSoliderType); compositeSoliderFlyeweight1.attack("上路"); compositeSoliderFlyeweight2.attack("中路"); System.out.println("---------------------------------"); System.out.println("單純享元模式是否共享對象:" + (soldierFlyweight1 == soldierFlyweight2)); System.out.println("複合享元模式是否共享對象:" + (compositeSoliderFlyeweight1 == compositeSoliderFlyeweight2)); }}複製代碼
複合享元模式中,組成複合享元對象的每一個單純享元對象擁有本身的內部狀態,而每一個單純享元對象的外部狀態都和複合享元對象的外部狀態相同。因此複合享元模式能夠對多個單純享元對象設置相同的外部狀態, 這也是複合享元模式的應用場景。
複合享元模式UML圖
享元模式總結
系統有大量類似或者相同對象。因爲這類對象的大量使用,形成內存的大量耗費。
須要緩衝池的場景,(享元池,也就是在須要屢次使用享元對象的時候)。
對象的大部分狀態均可之外部化,能夠將這些外部狀態傳入對象中。
優勢
大大減小對象的建立,下降系統的內存,使效率提升。
享元模式的外部狀態相對獨立,並且不會影響其內部狀態,從而使得享元對象能夠在不一樣的環境中被共享。
缺點
須要分離出外部狀態和內部狀態,提升了系統的複雜度。
讀取享元模式的外部狀態會使得運行時間稍微變長。
爲了感謝您的關注和喜好,碼之初爲正在找工做的小夥伴悄悄的送上一批乾貨,後臺發送」面試「關鍵字,便可領取隨機一份面試資料,祝全部小夥伴步步高昇,前程似錦!