設計模式--第10篇(享元模式)

一,享元模式

享元模式:

  1. 又叫蠅量模式,運用共享技術有效的支持大量的細粒度的對象;
  2. 常用於系統底層的開發,解決系統性的問題,如數據庫連接池,如果沒有再創建一個,有就直接拿來用;
  3. 能夠解決重複創建對象的內存浪費問題,當系統中有大量相似對象,需要緩衝池時,不需要總是創建新對象,從緩衝池直接獲取,降低系統內存提高效率;
  4. 經典的場景就是池技術,如數據庫連接池、string常量池、緩衝池等;

內部狀態: 對象共享出來的信息,存儲在享元對象內部,不隨環境改變而改變,如:圍棋的棋子顏色;
外部狀態: 不可共享的,對象依賴的一個標記,隨環境而改變,如:圍棋的棋子位置;

二,原理類圖

在這裏插入圖片描述
意圖: 運用共享技術有效地支持大量細粒度的對象。
適用性:

  1. 一個應用程序使用了大量的對象。完全由於使用大量的對象,造成很大的存儲開銷。
  2. 對象的大多數狀態都可變爲外部狀態。如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代很多組對象。
  3. 應用程序不依賴於對象標識。由於Flyweight 對象可以被共享,對於概念上明顯有別的對象,標識測試將返回真值。

三,實例

FlyWeight(抽象的享元角色)

package com.neei.flyweight;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/11  20:59
 * @Description: 遊學網
 * @throws:
 */
public abstract class WebSite {
    abstract void useWeb(User user);
}

ConcreteFlyWeight(共享具體實現)

package com.neei.flyweight;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/11  21:01
 * @Description: 遊學網
 * @throws:
 */
public class ConcreteWebSite extends WebSite {
    private String type;

    public ConcreteWebSite(String type) {
        this.type = type;
    }

    @Override
    void useWeb(User user) {
        System.out.println(user.getName() + "打開的網站:" + type);
    }
}


UnsharedConcreteFlyWeight(非共享具體實現)

package com.neei.flyweight;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/11  21:13
 * @Description: 遊學網
 * @throws:
 */
public class User {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

FlyWeightFactory(享元工廠類)

package com.neei.flyweight;

import java.util.HashMap;
import java.util.Map;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/11  21:02
 * @Description: 遊學網
 * @throws:
 */
public class WebSiteFactory {

    private Map<String, WebSite> pool = new HashMap<>();


    public WebSite getWebSite(String type) {
        if (!pool.containsKey(type)) {
            pool.put(type, new ConcreteWebSite(type));
        }
        return pool.get(type);
    }

    public int size() {
        return pool.size();
    }
}

調用

package com.neei.flyweight;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/11  21:05
 * @Description: 遊學網
 * @throws:
 */
public class Client {
    public static void main(String[] args) {

        WebSiteFactory factory = new WebSiteFactory();
        WebSite webSite = factory.getWebSite("淘寶");
        webSite.useWeb(new User("張三"));
        WebSite webSite1 = factory.getWebSite("天貓");
        webSite1.useWeb(new User("李四"));
        WebSite webSite2 = factory.getWebSite("淘寶");
        webSite2.useWeb(new User("王五"));
        WebSite webSite3 = factory.getWebSite("淘寶");
        webSite3.useWeb(new User("趙六"));
        System.out.println("池中總數:"+factory.size());
    }
}

四,源碼分析

JDK源碼中使用的享元模式,如java.lang.Integer#valueOf

	private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }


	public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章