天天看點

設計模式 _第十六招式_享元模式

一、定義

享元模式(Flyweight Pattern)是池技術的重要實作方式其定義如下:使用共享對象可以有效地支援大量的細粒度的對象。

享元模式的定義為我們提出列兩個要求:細粒度對象和共享對象。我們知道配置設定太多的對象到應用程式中将有損程式的性能,同時還容易造成記憶體溢出,那怎麼規避呢 ?就是享元模式提供的共享技術。

要求細粒度對象,則會導緻對象的數量多且屬性都非常相似,為了抽取相同的屬性, 可以将對象内容分為兩個部分:内部狀态(instrinsic)與外部狀态(extrinsic)。

  • 内部狀态

    内部狀态是對象可共享出來的資訊。存儲在享元對象内部并且不會随着環境改變而改變,他們可以作為一個對象的動态附件資訊, 不直接儲存在對象内部,如一個學生類中的 所屬學校資訊等。

  • 外部狀态

    外部狀态是對象依賴的一些屬性,是随環境改變而改變的、不可以共享的狀态,如一個使用者類的 建立時間、姓名等。

二、代碼示範

2.1 通用類圖

設計模式 _第十六招式_享元模式

2.2 角色說明

  • Flyweight–抽象享元角色

    簡單說是一個産品的抽象類,同時定義了對象的外部狀态和内部狀态的接口或實作。

    -ConcreteFlyweight–具體享元角色

    具體的一個産品類,該類中内部狀态處理應該與環境無關,不應該出現一個操作改變了内部狀态,同時修改了外部狀态。

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

    不存在外部狀态或線程安全不能夠用共享技術的對象,該對象一般不會出現在享元工廠中。

  • FlyweightFactory–享元工廠

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

2.3 抽象享元角色

抽象享元角色一般為抽象類,在實際項目中,一般是一個實作類,它是描述一類事物的方法。抽象角色中,一般需要把外部狀态和内部狀态定義出來,避免子類的随意擴充。

package com.design.flyweiht.pattern;

/**
 * @description 抽象享元對象
 * @date: 2019/9/28 17:24
 * @version: v 0.1
 */
public abstract class Flyweight {
    //内部狀态
    private String intrinsic;
    //外部狀态
    protected final String extrinsic;

    public Flyweight(String _extrinsic) {
        this.extrinsic = _extrinsic;
    }

    //定義業務操作
    public abstract void operate();

    public String getIntrinsic() {
        return intrinsic;
    }

    public void setIntrinsic(String intrinsic) {
        this.intrinsic = intrinsic;
    }

    public String getExtrinsic() {
        return extrinsic;
    }
}

           

2.4 具體享元角色

實作自己的業務邏輯,然後接收外部狀态,以便内部業務邏輯對外部狀态的依賴。

package com.design.flyweiht.pattern;

/**
 * @description 具體享元對象
 * @date: 2019/9/28 17:31
 * @version: v 0.1
 */
public class ConcreteFlyweight1 extends Flyweight {
    public ConcreteFlyweight1(String _extrinsic) {
        super(_extrinsic);
    }

    @Override
    public void operate() {
        System.out.println("ConcreteFlyweight1 operate");
    }
}

           

2.5 享元工廠

package com.design.flyweiht.pattern;

import java.util.HashMap;

/**
 * @description 享元工廠
 * @date: 2019/9/28 17:47
 * @version: v 0.1
 */
public class FlyweightFactory {
    //定義一個容器
    private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();

    public static Flyweight getFlyweight(String extriansic) {
        //傳回需要的對象
        Flyweight flyweight = null;
        if (pool.containsKey(extriansic)) {
            flyweight = pool.get(extriansic);
            System.out.println("FlyweightFactory  :" + extriansic + ":  come from pool");
        } else {
            //根據外部狀态建立享元對象
            flyweight = new ConcreteFlyweight1(extriansic);
            //放到池中
            pool.put(extriansic, flyweight);
            System.out.println("FlyweightFactory  :" + extriansic + ":  not come from pool");
        }
        return flyweight;
    }
}


           

2.6 驗證場景類

package com.design.flyweiht.pattern;

/**
 * @description TODO
 * @date: 2019/9/28 17:57
 * @version: v 0.1
 */
public class Client {
    public  static  void  main(String args[]){
        String extriansic= "tester";
        Flyweight  flyweight1 = FlyweightFactory.getFlyweight(extriansic);
        flyweight1.operate();
        Flyweight  flyweight2 = FlyweightFactory.getFlyweight(extriansic);
        flyweight2.operate();
    }
}

           

2.7 運作結果

FlyweightFactory  :tester:  not come from pool
ConcreteFlyweight1 operate
FlyweightFactory  :tester:  come from pool
ConcreteFlyweight1 operate
           

三、優點

享元模式是一個非常簡單的模式,可以大大減少應用程式建立的對象,降低程式記憶體占用,增加程式的性能;

四、缺點

由于需要區分内部狀态和外部狀态,而且外部狀态是固化的,可能導緻系統複雜性增加。

五、應用場景

  • 系統中存在大量的相似對象。
  • 細粒度的對象中外部狀态相似,且内部狀态與環境無關。
  • 需要緩沖池的場景。

六、注意事項

繼續閱讀