天天看點

設計模式之——享元模式一、基本介紹二、包含角色三、案例及UML類圖四、适用場景五、其它

一、基本介紹

享元模式(結構型):運用共享技術來有効地支援大量細粒度對象的複用。它通過共享已經存在的對象來大幅度減少需要建立的對象數量、避免大量相似類的開銷,進而提高系統資源的使用率。

二、包含角色

1.抽象享元角色:為具體享元規範需要實作的公共接口,非享元的外部狀态以參數的形式通過方法傳入。

2.具體享元角色:實作抽象享元角色中所規定的接口,為需要共享的對象。

3.非享元角色:不共享的外部狀态,作為享元角色所需要的外部參數,以形參的方式傳入。

4.享元工廠角色:負責建立和管理享元角色,一般用緩存管理這些對象。

三、案例及UML類圖

案例說明:

          驗證碼主要分為常見驗證碼,即數字+字母的形式,和計算類型驗證碼,即15+10=?類型的, 本公司主要提供驗證碼服務,其它要使用該服務的公司通過調用接口去建立使用該驗證碼, 因為通路量高,是以需要使用緩存來管理這些對象,節省記憶體開銷。

UML類圖:
設計模式之——享元模式一、基本介紹二、包含角色三、案例及UML類圖四、适用場景五、其它

類Captcha:

public interface Captcha {

    /**
     * 享元角色的公共接口
     * @param captchaArgs 外部狀态,即變化的部分,通過參數傳遞,可以為對象或其它的參數。
     */
    void product(CaptchaArgs captchaArgs);
}
           

說明:驗證碼接口,抽象享元角色,定義驗證碼公共接口。

類ComputeCaptcha:

public class ComputeCaptcha implements Captcha {

    @Override
    public void product(CaptchaArgs captchaArgs) {
        System.out.println("生成了一個寬度:"+captchaArgs.getWidth()+"," +
                "高度:"+captchaArgs.getHeight()+"複雜度:"+captchaArgs.getComplexity()+"的計算型驗證碼。");
    }
}           

說明:計算型驗證碼類,具體享元角色,需要共享的類。

類NormalCaptcha:

public class NormalCaptcha implements Captcha {


    @Override
    public void product(CaptchaArgs captchaArgs) {
        System.out.println("生成了一個寬度:"+captchaArgs.getWidth()+"," +
                "高度:"+captchaArgs.getHeight()+"複雜度:"+captchaArgs.getComplexity()+"的常見驗證碼。");
    }
}           

說明:常見的驗證碼,如輸入字母和數字的,具體享元角色,需要共享的類。

類CaptchaArgs:

public class CaptchaArgs {


    public CaptchaArgs(Integer width, Integer height, String complexity) {
        this.width = width;
        this.height = height;
        this.complexity = complexity;
    }

    private Integer width;

    private Integer height;

    /**
     * 複雜度
     */
    private String complexity;


    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public String getComplexity() {
        return complexity;
    }

    public void setComplexity(String complexity) {
        this.complexity = complexity;
    }
}           

說明:驗證碼參數類,非享元角色,用于接收驗證碼的外部變化參數。

類FlyweightFactory:

public class FlyweightFactory {

    /**
     * 享元角色的緩存,key是驗證碼的類型,都是單例的
     */
    private Map<Integer, Captcha> captchaMap = new ConcurrentHashMap<>();

    /**
     * 初始化時,先添加好其需要共享的享元角色
     */
    public FlyweightFactory() {
        //0表示正常驗證碼
        captchaMap.put(0,new NormalCaptcha());
        //1表示輸入型驗證碼
        captchaMap.put(1,new ComputeCaptcha());
    }

    /**
     * 享元模式的擷取,隻傳回緩存中的,做到共享。
     * @param type 類型,0是正常驗證碼。1是計算型驗證碼
     * @return 驗證碼類
     */
    public Captcha getCaptcha(int type) {
        if(captchaMap.keySet().contains(type)) {
            return captchaMap.get(type);
        }else {
            return null;
        }
    }

}           

說明:驗證碼工廠,享元工廠,用一個緩存儲存需要共享的對象,為外部提供需要共享的變量。

類FlyweightTest:

public class FlyweightTest {

    public static void main(String[] args) {
        FlyweightFactory flyweightFactory = new FlyweightFactory();
        //擷取一個正常驗證碼
        Captcha captcha = flyweightFactory.getCaptcha(0);
        // 生成一個長寬為120且簡單的正常驗證碼
        captcha.product(new CaptchaArgs(120,120,"簡單"));
        //擷取一個計算型驗證碼
        captcha = flyweightFactory.getCaptcha(1);
        // 生成一個長寬為200且複雜的計算型驗證碼
        captcha.product(new CaptchaArgs(200,200,"複雜"));
    }


}           

說明:測試及用戶端類。

四、适用場景

1.系統中存在大量相同或相似的對象,這些對象耗費大量的記憶體資源。

2.常見的緩存

五、其它

注意:由于享元模式需要額外維護一個儲存享元的資料結構,是以應當在享元對象被使用得足夠多時才值得使用享元模式。

繼續閱讀