系统往往只需要一个享元工厂的实例,所以享元工厂可以设计成单例模式。
复合享元模式
结构图

所涉及的角色
(1)抽象享元(Flyweight)角色:此角色是所有具体享元类的超类,为这些类规定需要实现的公共接口。那些需要外部状态的操作可以通过方法的参数传入。抽象享元的接口使得享元共享成为可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
(2)具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元角色又叫做单纯具体享元角色,因为复合享元角色是由单纯具体享元角色通过复合而成的。
(3)复合享元(UnsharableFlyweight)角色:复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。
(4)享元工厂(FlyweightFactory)角色:享元工厂负责创建和管理享元对象。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象时,享元工厂角色检查是否已有一个符合要求的享元对象,如果有,则提供,如果没有,则创建。
(5)客户端(Client)角色: 客户单角色需要维护一个对所有享元对象的引用,需要自行存储所有享元对象的外部状态。
代理实例
import java.util.*;
abstract class Flyweight
{
//一个示意性的方法,参数state是外部状态
public abstract void operation(String state);
}
class ConcreteFlyweight extends Flyweight
{
private Character intrinsicState = null;
//构造函数,内部状态作为参数传入
public ConcreteFlyweight(Character state)
{
this.intrinsicState = state;
}
//外部状态作为参数传入,改变方法的行为,但不改变对象的内部状态
public void operation(String state)
{
System.out.println("Intrinsic State = " + intrinsicState + ",Extrinsic State = " + state);
}
}
class ConcreteCompositeFlyweight extends Flyweight
{
private Map
files = new HashMap
(10); private Flyweight flyweight; public ConcreteCompositeFlyweight() {} public void add(Character key,Flyweight fly) { files.put(key,fly); } public void operation(String extrinsicState) { Flyweight fly = null; for(Iterator it = files.entrySet().iterator();it.hasNext();) { Map.Entry e = (Map.Entry)it.next(); fly = (Flyweight)e.getValue(); fly.operation(extrinsicState); } } } class FlyweightFactory { private Map
files = new HashMap
(); private Flyweight lnkFlyweight; public FlyweightFactory() {} public Flyweight factory(Character state) { if(files.containsKey(state)) { return files.get(state); } else{ Flyweight fly = new ConcreteFlyweight(state); files.put(state,fly); return fly; } } //符合享元工厂方法,一般传入一个聚集对象,这里换入String,因为可以分解成Character public Flyweight factory(String compositeState) { ConcreteCompositeFlyweight compositeFly = new ConcreteCompositeFlyweight(); int length = compositeState.length(); Character state = null; for(int i=0;i
通过以上代码可以看到,客户对象向享元工厂申请了一个内部状态为"bcb",外部状态为"Composite Call"的 享元对象。调用享元工厂的 辅助方法factory.checkFlyweight(),可以看到系统一共创建了两个单纯享元对象,分别对应"b"和"c"两种内部状态。
使用场景
当以下所