一、FlyWeight模式定义:
运用共享技术有效地支持大量细粒度对象。
二、模式解说
也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。在Flyweight模式中,由于要产生各种各样的对象,所以在Flyweight(享元)模式中常出现Factory模式。Flyweight的内部状态是用来共享的,Flyweightfactory负责维护一个对象存储池(FlyweightPool)来存放内部状态的对象。Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。
三、结构图
四、 原理:
享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State).
一个内蕴状态是存储在享元对象内部的,并且不会随环境改变而有所不同.因此,一个享元可以具有内蕴状态并可以共享.
一个外蕴状态是随环境改变而改变的,不可以共享状态.享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传到享元对象内部.
外蕴状态不可以影响享元对象的内蕴状态,他们是相互独立的.所有的内蕴状态在对象创建完后就不可再改变.
举一个现实中的例子,某淘宝店经营一款畅销女式皮鞋,每天需要处理大量的订单信息,在订单中需要注明客户购买的皮鞋信息,我们将皮鞋产品抽象出来:
class Shoe {
String color;// 颜色
int size;// 尺寸
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
public class ConcreteShoe extends Shoe {
String position;// 库存位置
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
class ShoeFactory {
Collection<ConcreteShoe> shoes = new ArrayList<ConcreteShoe>();
Shoe getSheo(String color, int size, String position) {
// 首先在缓存中查找对象
for (ConcreteShoe shoe : shoes) {
if (shoe.getColor() == color && shoe.getSize() == size) {
// 在缓存中命中对象后还原对象的外部属性
shoe.setPosition(position);
return shoe;
}
}
// 如果缓存未命中则新建对象并加入缓存
ConcreteShoe shoe = new ConcreteShoe();
shoe.setColor(color);
shoe.setSize(size);
shoe.setPosition(position);
shoes.add(shoe);
return shoe;
}
}
当我们在自己的业务场景中应用享元模式时,一定要注意分清对象的内部状态和外部状态,享元模式强调缓存的版本只能包含对象的内部状态。
事实上,Java中的String和Integer类都是享元模式的应用的例子,String类内部对所有的字符串对象进行缓存,相同的字符串在内存中只会保留一个版本。类似的,Integer类在内部对小于255的整数也进行了缓存。
五、 适用性Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况都成立时使用Flyweight模式。
1)
2)
3)
4)
5)
六、优缺点
1)享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
2)享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。