设计模式(10) : 享元模式

定义:

  • 提供了减少对象数量从而改善应用所需的对象结构的方法

说到享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。
比如创建字符串对象时, 如果每次都需要创建一个新的字符串对象的话,内存开销会很大,所以如果第一次创建了字符串对象“hello“,下次再创建相同的字符串”hello“时,只需把它的引用指向”hello“即可,这样就实现了字符串在内存中的共享。

类型:

  • 结构型

使用场景

  • 常常应用于系统底层的开发, 提高系统性能
  • 系统有大量相似对象, 需要缓冲池的场景

coding

当前社会男多女少, 共享女朋友势在必行.
以下代码不做解释,请自行体会.

public class GirlFriend {
    private String id;
    private String name;
}
public class FlyweightGirlFriendFactory {

    private static Map map = new HashMap<>(16);

    private static Set all;

    static {
        map.put("5", new GirlFriend("5", "女朋友5号"));
        map.put("4", new GirlFriend("4", "女朋友4号"));
        map.put("3", new GirlFriend("3", "女朋友3号"));
        map.put("2", new GirlFriend("2", "女朋友2号"));
        map.put("1", new GirlFriend("1", "女朋友1号"));
        all = map.keySet();
    }

    public static GirlFriend getGirlFriend(String id){
        if(!all.contains(id)){
            throw new RuntimeException("这个女朋友不出租");
        }else if(!map.containsKey(id)){
            throw new RuntimeException("这个女朋友被租出去了,还没还回来!");
        }
        return map.remove(id);
    }

    public static void returnGirlFriend(GirlFriend girlFriend){
        if(!all.contains(girlFriend.getId())){
            throw new RuntimeException("emmm....");
        }
        map.put(girlFriend.getId(), girlFriend);
    }
}

写完感觉怪怪的..., 好像有哪里不对劲

源码中的应用

除了刚才提到的String连接池之外, 开发中最常用的Integer类,也应用了享元模式

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

Integer 会默认缓存-128-127之间的数字(可以通过jvm参数改变这个值),存放到一个数组中, 因为这些数字是非常常用的, 复用这些对象可以减少重复创建的资源消耗.

优点:

  • 减少对象的创建, 提高运行效率
  • 降低内存中对象的数量, 节省系统内存

缺点:

  • 线程安全使用共享的对象, 会带来线程安全问题
  • 增加了系统的复杂度

github源码

你可能感兴趣的:(设计模式(10) : 享元模式)