• <menu id="gyiem"><menu id="gyiem"></menu></menu>
  • <menu id="gyiem"><code id="gyiem"></code></menu>

    Java設計模式(十一) 享元模式

    原創文章,轉載請務必將下面這段話置于文章開頭處(保留超鏈接)。
    本文轉發自技術世界原文鏈接 http://www.luozeyang.com/design_pattern/flyweight/

    享元模式介紹

    享元模式適用場景

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

    享元模式定義

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

    享元模式類圖

    享元模式類圖如下
    FlyWeight Pattern Class Diagram

    享元模式角色劃分

    • FlyWeight 享元接口或者(抽象享元類),定義共享接口
    • ConcreteFlyWeight 具體享元類,該類實例將實現共享
    • UnSharedConcreteFlyWeight 非共享享元實現類
    • FlyWeightFactory 享元工廠類,控制實例的創建和共享

    內部狀態 vs. 外部狀態

    • 內部狀態是存儲在享元對象內部,一般在構造時確定或通過setter設置,并且不會隨環境改變而改變的狀態,因此內部狀態可以共享。
    • 外部狀態是隨環境改變而改變、不可以共享的狀態。外部狀態在需要使用時通過客戶端傳入享元對象。外部狀態必須由客戶端保存。

    享元模式實例解析

    本文代碼可從作者Github下載

    享元接口,定義共享接口

    1
    2
    3
    4
    5
    6
    7
    package com.jasongj.flyweight;

    public interface FlyWeight {

    void action(String externalState);

    }

    具體享元類,實現享元接口。該類的對象將被復用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.jasongj.flyweight;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class ConcreteFlyWeight implements FlyWeight {

    private static final Logger LOG = LoggerFactory.getLogger(ConcreteFlyWeight.class);

    private String name;

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

    @Override
    public void action(String externalState) {
    LOG.info("name = {}, outerState = {}", this.name, externalState);
    }

    }

    享元模式中,最關鍵的享元工廠。它將維護已創建的享元實例,并通過實例標記(一般用內部狀態)去索引對應的實例。當目標對象未創建時,享元工廠負責創建實例并將其加入標記-對象映射。當目標對象已創建時,享元工廠直接返回已有實例,實現對象的復用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.jasongj.factory;

    import java.util.concurrent.ConcurrentHashMap;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import com.jasongj.flyweight.ConcreteFlyWeight;
    import com.jasongj.flyweight.FlyWeight;

    public class FlyWeightFactory {

    private static final Logger LOG = LoggerFactory.getLogger(FlyWeightFactory.class);

    private static ConcurrentHashMap<String, FlyWeight> allFlyWeight = new ConcurrentHashMap<String, FlyWeight>();

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

    }

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

    本例中,name可以認為是內部狀態,在構造時確定。externalState屬于外部狀態,由客戶端在調用時傳入。

    享元模式分析

    享元模式優點

    • 享元模式的外部狀態相對獨立,使得對象可以在不同的環境中被復用(共享對象可以適應不同的外部環境)
    • 享元模式可共享相同或相似的細粒度對象,從而減少了內存消耗,同時降低了對象創建與垃圾回收的開銷

    享元模式缺點

    • 外部狀態由客戶端保存,共享對象讀取外部狀態的開銷可能比較大
    • 享元模式要求將內部狀態與外部狀態分離,這使得程序的邏輯復雜化,同時也增加了狀態維護成本

    享元模式已(未)遵循的OOP原則

    已遵循的OOP原則

    • 依賴倒置原則
    • 迪米特法則
    • 里氏替換原則
    • 接口隔離原則
    • 單一職責原則
    • 開閉原則

    未遵循的OOP原則

    • NA

    Java設計模式系列

    郭俊 Jason wechat
    歡迎關注作者微信公眾號【大數據架構】
    您的贊賞將支持作者繼續原創分享
    速赢彩app 内江 | 台山 | 商丘 | 普洱 | 定西 | 库尔勒 | 惠东 | 桂林 | 衢州 | 仙桃 | 崇左 | 滕州 | 霍邱 | 包头 | 三亚 | 保定 | 乐山 | 攀枝花 | 榆林 | 长垣 | 温岭 | 沛县 | 湖南长沙 | 永新 | 台中 | 长垣 | 广饶 | 辽阳 | 深圳 | 济宁 | 嘉善 | 琼海 | 湖州 | 湖州 | 沧州 | 沧州 | 惠东 | 定州 | 郴州 | 鹰潭 | 本溪 | 临沂 | 通辽 | 包头 | 十堰 | 日土 | 吴忠 | 白山 | 内蒙古呼和浩特 | 岳阳 | 芜湖 | 玉环 | 那曲 | 晋江 | 宁德 | 北海 | 恩施 | 云浮 | 垦利 | 涿州 | 海丰 | 台湾台湾 | 蓬莱 | 通化 | 怒江 | 黑河 | 抚州 | 榆林 | 邹城 | 衡水 | 东营 | 景德镇 | 延安 | 漳州 | 绥化 | 临汾 | 泸州 | 运城 | 漯河 | 九江 | 张家界 | 洛阳 | 海丰 | 姜堰 | 威海 | 昌都 | 阜新 | 巴音郭楞 | 威海 | 神木 | 馆陶 | 寿光 | 青海西宁 | 长葛 | 天长 | 阜阳 | 扬州 | 连云港 | 沧州 | 乳山 | 苍南 | 抚州 | 顺德 | 文昌 | 四平 | 曲靖 | 宜宾 | 醴陵 | 阿拉善盟 | 揭阳 | 绵阳 | 吕梁 | 台湾台湾 |