一、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)享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。