定义(百度百科):
享元模式(英语:Flyweight Pattern)是一种软件设计模式。
它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。
通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
UML类图:
具体代码:
public interface FlyWeight { void operation(String externalState); } public class ConcreteFlyweight implements FlyWeight { private String intrinsicState; public ConcreteFlyweight(String intrinsicState) { this.intrinsicState = intrinsicState; } @Override public void operation(String externalState) { System.out.println("ConcreteFlyweight " + externalState); } } public class UnSharedConcreteFlyWeight implements FlyWeight { @Override public void operation(String externalState) { System.out.println("UnSharedConcreteFlyWeight " + externalState); } private String allState; public UnSharedConcreteFlyWeight(String allState) { this.allState = allState; } } public class FlyWeightFactory { private static ConcurrentHashMap<String, FlyWeight> allFlyWeight = new ConcurrentHashMap<String, FlyWeight>(); public static FlyWeight getFlyWeight(String name) { if (allFlyWeight.get(name) == null) { synchronized (allFlyWeight) { if (allFlyWeight.get(name) == null) { FlyWeight flyWeight = new ConcreteFlyweight(name); allFlyWeight.put(name, flyWeight); } } } return allFlyWeight.get(name); } }
再提到各模块之前,先说明内外部状态,这对理解享元模式非常重要。
内部状态:内部状态是存储在享元对象内部,一般在构造时确定或通过setter设置,并且不会随环境改变而改变的状态,因此内部状态可以共享。
外部状态:外部状态是随环境改变而改变、不可以共享的状态。外部状态在需要使用时通过客户端传入享元对象。外部状态必须由客户端保存。
各模块说明:
FlyWeight:享元接口或者(抽象享元类),定义共享接口
ConcreteFlyWeight:具体享元类,该类实例将实现共享
UnSharedConcreteFlyWeight:非共享享元实现类
FlyWeightFactory:享元工厂类,控制实例的创建和共享
例子:
五子棋,围棋这类,把黑白子设置成享元类,坐标不是享元的而已。
系统人员权限管理,人员不是享元的,权限都是享元的。
适用场景:
如果一个系统中存在大量的相同或者相似的对象,由于这类对象的大量使用,会造成系统内存的耗费,可以使用享元模式来减少系统中对象的数量。
对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
优缺点:
优点:
享元模式可共享相同或相似的细粒度对象,减少了内存消耗
享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享
缺点:
外部状态由客户端保存,共享对象读取外部状态的开销可能比较大
享元模式要求将内部状态与外部状态分离,这使得程序的逻辑复杂化,同时也增加了状态维护成本
总结:享元模式的本质是对象的共享与状态的分离。