設計模式-享元模式

一、定義

享元模式(Flyweight Pattern)是池技術的重要實現方式,其定義如下:Use sharing to support large numbers of fine-grained objects efficiently.(使用共享對象可有效地支持大量的細粒度的對象。)

享元模式的定義為我們提出了兩個要求:細粒度的對象和共享對象。我們知道分配太多的對象到應用程序中將有損程序的性能,同時還容易造成內存溢出,那怎么避免呢?就是享元模式提到的共享技術。我們先來了解一下對象的內部狀態和外部狀態。

要求細粒度對象,那么不可避免地使得對象數量多且性質相近,那我們就將這些對象的信息分為兩個部分:內部狀態(intrinsic)與外部狀態(extrinsic)。

  • 內部狀態

內部狀態是對象可共享出來的信息,存儲在享元對象內部并且不會隨環境改變而改變,它們可以作為一個對象的動態附加信息,不必直接儲存在具體某個對象中,屬于可以共享的部分。

  • 外部狀態

外部狀態是對象得以依賴的一個標記,是隨環境改變而改變的、不可以共享的狀態。

有了對象的兩個狀態,我們就可以來看享元模式的通用類圖,如圖所示。

享元模式的通用類圖

類圖也很簡單,我們先來看我們享元模式角色名稱。

  • Flyweight——抽象享元角色

它簡單地說就是一個產品的抽象類,同時定義出對象的外部狀態和內部狀態的接口或實現。

  • ConcreteFlyweight——具體享元角色

具體的一個產品類,實現抽象角色定義的業務。該角色中需要注意的是內部狀態處理應 該與環境無關,不應該出現一個操作改變了內部狀態,同時修改了外部狀態,這是絕對不允 許的。

  • unsharedConcreteFlyweight——不可共享的享元角色

不存在外部狀態或者安全要求(如線程安全)不能夠使用共享技術的對象,該對象一般 不會出現在享元工廠中。

  • FlyweightFactory——享元工廠

職責非常簡單,就是構造一個池容器,同時提供從池中獲得對象的方法。

享元模式的目的在于運用共享技術,使得一些細粒度的對象可以共享,我們的設計確實 也應該這樣,多使用細粒度的對象,便于重用或重構。我來看享元模式的通用代碼,先看抽 象享元角色。

//抽象享元角色

public abstract class Flyweight { 
    //內部狀態 
    private String intrinsic; 
    //外部狀態 
    protected final String Extrinsic; 
    //要求享元角色必須接受外部狀態 
    public Flyweight(String _Extrinsic){
        this.Extrinsic = _Extrinsic;
    }
    //定義業務操作
    public abstract void operate();
    //內部狀態的getter/setter 
    public String getIntrinsic() {
        return intrinsic;
    }
    public void setIntrinsic(String intrinsic) {
        this.intrinsic = intrinsic;
    }
}

抽象享元角色一般為抽象類,在實際項目中,一般是一個實現類,它是描述一類事物的 方法。在抽象角色中,一般需要把外部狀態和內部狀態(當然了,可以沒有內部狀態,只有 行為也是可以的)定義出來,避免子類的隨意擴展。

//具體享元角色

public class ConcreteFlyweight1 extends Flyweight{ 
    //接受外部狀態
    public ConcreteFlyweight1(String _Extrinsic){
        super(_Extrinsic);
    }
    //根據外部狀態進行邏輯處理
    public void operate(){
        //業務邏輯
    }
} 

public class ConcreteFlyweight2 extends Flyweight{ 
    //接受外部狀態
    public ConcreteFlyweight2(String _Extrinsic){
        super(_Extrinsic);
    }
    //根據外部狀態進行邏輯處理
    public void operate(){
        //業務邏輯
    }
}

這很簡單,實現自己的業務邏輯,然后接收外部狀態,以便內部業務邏輯對外部狀態的依賴。注意,我們在抽象享元中對外部狀態加上了final關鍵字,防止意外產生,什么意外?獲得了一個外部狀態,然后無意修改了一下,池就混亂了!

在程序開發中,確認只需要一次賦值的屬性則設置為final類型,避免無意修改導 致邏輯混亂,特別是Session級的常量或變量。

//享元工廠

public class FlyweightFactory {
    //定義一個池容器
    private static HashMap<String,Flyweight> pool= new HashMap<String,Flyweight>();
    //享元工廠
    public static Flyweight getFlyweight(String Extrinsic){ 
    //需要返回的對象
    Flyweight flyweight = null;
    //在池中沒有該對象 
    if(pool.containsKey(Extrinsic)){
        flyweight = pool.get(Extrinsic);
    } else { 
        //根據外部狀態創建享元對象
        flyweight = new ConcreteFlyweight1(Extrinsic); 
        //放置到池中
        pool.put(Extrinsic, flyweight);
        }
    return flyweight;
    }
}

二、應用

2.1 優點和缺點

享元模式是一個非常簡單的模式,它可以大大減少應用程序創建的對象,降低程序內存 的占用,增強程序的性能,但它同時也提高了系統復雜性,需要分離出外部狀態和內部狀 態,而且外部狀態具有固化特性,不應該隨內部狀態改變而改變,否則導致系統的邏輯混 亂。

2.2 使用場景

在如下場景中則可以選擇使用享元模式。

  • 系統中存在大量的相似對象。
  • 細粒度的對象都具備較接近的外部狀態,而且內部狀態與環境無關,也就是說對象沒 有特定身份。
  • 需要緩沖池的場景。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 定義 Flyweight在拳擊比賽中指最輕量級,即“蠅量級”或“雨量級”。這里選擇使用“享元模式”的意譯,是因為這...
    步積閱讀 1,648評論 0 2
  • 享元模式(Flyweight Pattern):運用共享技術有效地支持大量細粒度對象的復用。系統只使用少量的對象,...
    breezedancer閱讀 1,923評論 2 51
  • 原文地址:LoveDev 享元模式(Flyweight Pattern):運用共享技術有效地支持大量細粒度對象的復...
    KevinLive閱讀 307評論 0 0
  • 享元模式——運用共享技術有效地支持大量細粒度的對象。享元模式可以避免大量相似類的開銷,在軟件開發中如果需要生成大量...
    語文小子閱讀 487評論 0 0
  • 一、概念 主要用于減少創建對象的數量,以減少內存占用和提高性能。 1.1、定義 運用共享技術有效地支持大量細粒度對...
    雙魚子曰1987閱讀 132評論 0 0