天天看點

亨元模式亨元模式介紹亨元模式執行個體分析亨元模式分析

亨元模式介紹

亨元模式适用場景

面向對象技術可以很好的解決一些靈活性或可拓展性的問題,但在很多情況下需要在系統中增加類和對象的個數。當對象數量太多時,将導緻對象建立及垃圾回收的代價過高,造成性能下降等問題。亨元模式通過共享相同或者類似的細粒度對象解決這一類問題。

亨元模式定義

亨元模式(Flyweight Pattern),又稱輕量級模式(這也是其英文名FlyWeight的原因),通過共享技術有效的實作了大量細粒度對象的服用。

亨元模式類圖

亨元模式類圖如下:

亨元模式亨元模式介紹亨元模式執行個體分析亨元模式分析

亨元模式角色劃分

  1. FlyWeight亨元接口或者(抽象亨元類),定義共享接口
  2. ConcreteFlyWeight:具體亨元類,該執行個體将實作共享
  3. UnsharedConcreteFlyWeight:非共享亨元實作類
  4. FlyWeightFactory:亨元工廠類,控制執行個體的建立和共享。

内部狀态 VS 外部狀态

  1. 内部狀态是存儲在亨元對象内部,一般在構造是确定或通過setter設定,并且不會随環境改變而改變的狀态,是以内部狀态可以共享。
  2. 外部狀态是随環境變化而變化,不可以共享的狀态。外部狀态在需要使用時通過用戶端傳入亨元對象。外部狀态必須由用戶端儲存。

亨元模式執行個體分析

亨元接口,定義共享接口

public interface FlyWeight {
    void action(String externalState);
}
           

具體亨元類,實作亨元接口。該類的對象将被複用

public class ConcreteFlyWeight implements FlyWeight {
    private String name;

    public ConcreteFlyWeight(String name) {
        this.name = name;
    }

    @Override
    public void action(String externalState) {
        System.out.println(String.format("name = %s, outerState = %s", this.name, externalState));
    }
}
           

亨元模式中,最關鍵的是亨元工廠。它将維護已建立的亨元執行個體,并通過執行個體标記(一般用内部狀态)去索引對應的執行個體。當目标對象未建立時,亨元工廠負責建立執行個體并将其加入标記-對象映射。當目标對象已建立時,亨元工廠直接傳回已有執行個體,實作對象的複用。

public class FlyWeightFactory {
    private static ConcurrentHashMap<String,FlyWeight> allFlyWeight = new ConcurrentHashMap<>();

    public static FlyWeight getFlyWeight(String name) {
        if(allFlyWeight.get(name) == null){
            synchronized (allFlyWeight){
                if(allFlyWeight.get(name) == null){
                    System.out.println(String.format("Instance of name = %s does not exist, creating it",name));
                    FlyWeight flyWeight = new ConcreteFlyWeight(name);
                    System.out.println(String.format("Instance of name = %s created",name));
                    allFlyWeight.put(name, flyWeight);
                }
            }
        }
        return  allFlyWeight.get(name);
    }
}
           

從上面的代碼中可以看到,亨元模式中對象的複用完全依靠亨元工廠。同時本例中實作了對象建立的懶加載。并且為了保證線程安全,本文使用的雙重檢查(Double Check)。

本例中,

name

可以認為時内部狀态,在構造是确定。

externalState

屬于外部狀态,由用戶端在調用時傳入。

測試類

public class FlyWeightTest {
    public static void main(String[] args) {
        FlyWeight sjj = FlyWeightFactory.getFlyWeight("sjj");
        sjj.action("wj");
    }
}
           

結果輸出

Instance of name = sjj does not exist, creating it
Instance of name = sjj created
name = sjj, outerState = wj
           

亨元模式分析

亨元模式優點

  1. 亨元模式的外部狀态相對獨立,使得對象可以在不同的環境中被複用(共享對象可以使用不同的外部環境)
  2. 亨元模式可共享相同或類似的細粒度對象,進而減少了記憶體消耗,同時降低了對象建立與垃圾回收的開銷

亨元模式缺點

  1. 外部狀态由用戶端儲存,共享對象讀取外部狀态的開銷可能比較大
  2. 亨元模式要求将内部狀态與外部狀态分離,這使得程式的邏輯複雜化,同時也增加了狀态維護成本。

繼續閱讀