这名字谁起的......简直了......
说实话,看到这个模式的时候,一头雾水。什么叫享元?什么又叫flyweight?这个名字对理解享元模式起到了极大的反作用。
言归正传,享元,就是共享元数据,而元数据应该是flyweight的,也就是轻量的。而我对享元的总结就是:
为了减少在堆中频繁分配一个轻量级类的开销,而将已经开立的该类的实例保存起来,当后续出现同样的开立请求时,不进行重复的内存分配,而直接返回以前开立并保存的实例。
看了这些不知道大家脑海中想到了什么。我首先想到的一个类就是String!大家应该知道,同样一个字符串“abcdef”,如果不是通过`new String("abcdef")来分配的话,其实它对应的地址是一个,并且都放在常量区。String就是使用了享元模式,当字符串相同时,不再新生成对象,而是直接返回之前已经保存起来的可用对象。
享元模式的核心是:使用一个HashMap来保存并返回需要的对象。除此之外,我看网上很多关于享元模式的展开和应用都是空穴来风,还是要理解其本质的内容。
这个图很容易懂,就是通过接口来定义享元的行为,通过工厂返回享元对象,客户直接调用工厂。而为什么要区分出ConcreteFlyweight和UnSharedConcreteFlyweight呢?我个人认为简直是没事找事。当一个类要作为享元,一次实例化后被多处共享,就是ConcreteFlyweight;如果一个类里面存在某些一般不会改变的属性,就把这些属性单独抽象出来做成一个ConcreteFlyweight,而原来的整个类就是UnSharedConcreteFlyweight。唉,搞这些概念出来简直是无病呻吟。
其实享元真的很简单,就看这个工厂怎么写:
//享元工厂角色类
public class FlyweightFactory {
// 一个用来存所有享元对象的集合 String表示对象的键的类型 ->内蕴状态 ;Flyweight表示对象值的类型
private Map<String, Flyweight> files = new ConcurrentHashMap<String, Flyweight>();
public Flyweight factory(String intrinsicState) {
// 先从缓存中查找对象
Flyweight fly = files.get(intrinsicState);
if (fly == null) {
// 如果对象不存在则创建一个新的Flyweight对象
fly = new ConcreteFlyweight(intrinsicState);
// 把这个新的Flyweight对象添加到缓存中
files.putIfAbsent(intrinsicState, fly);
}
return fly;
}
}
目的就是为了减少新的对象的生成,降低消耗。