设计模式--第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);
    }

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