享元模式是对象的结构模式。
享元模式以共享的方式高效的支持大量的细粒度对象。
享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External)。
一个内蕴状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的。因此,一个享元可以具有内蕴状态并可以共享。
一个外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入享元对象内部。
外蕴状态不可以影响享元对象的内蕴状态。也就是说,它们是相互独立的。
享元模式的种类
- 单纯享元模式
- 复合享元模式
单纯享元模式
角色如下:
- 抽象享元角色:此角色是所有具体享元类的超类,为这些类规定出需要实现的公共接口。
- 具体享元角色(ConcreteFlyweight): 实现抽象享元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须于对象所处的周围环境无关,从而使得享元对象可以在系统内共享。
- 享元工厂角色(FlyweightFactory): 本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当的共享。
- 客户端角色:本角色需要维护一个对所有享元对象的引用。本角色需要自行 存储所有享元对象的外蕴状态。
示意源码
抽象享元角色 Flyweight
代码语言:javascript复制public abstract class Flyweight {
//一个示意性方法,参数state是外蕴状态
public abstract void operation(String state);
}
具体享元角色 ConcreteFlyweight
代码语言:javascript复制public class ConcreteFlyweight extends Flyweight {
private Character intrinsicState = null;
/**
* 构造函数,内蕴状态作为参量传入
* @param state
*/
public ConcreteFlyweight(Character state){
this.intrinsicState = state;
}
/**
* 外蕴状态作为参量传入方法中,改变方法的行为,
* 但是并不改变对象的内蕴状态
*/
@Override
public void operation(String state) {
// TODO Auto-generated method stub
System.out.println("nInstrinsic State = " intrinsicState ".Extrinsic State = " state);
}
}
享元工厂角色 FlyweightFactory
代码语言:javascript复制public class FlyweightFactory {
private HashMap flies = new HashMap();
private Flyweight InkFlyweight;
public FlyweightFactory(){}
public Flyweight factory(Character state){
if(flies.containsKey(state)){
return (Flyweight)flies.get(state);
}else{
Flyweight fly = new ConcreteFlyweight(state);
flies.put(state, fly);
return fly;
}
}
/**
* 辅助方法
*/
public void checkFlyweight(){
Flyweight fly;
int i =0;
System.out.println("n====checkFlyweight()=====");
for(Iterator it = flies.entrySet().iterator();it.hasNext();){
Map.Entry e = (Map.Entry)it.next();
System.out.println("Item " ( i) ":" e.getKey());
}
System.out.println("======checkFlyweight()======");
}
}
客户端调用
代码语言:javascript复制public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个享元工厂对象
FlyweightFactory factory = new FlyweightFactory();
//向享元工厂对象请求一个内蕴状态为‘a’的享元对象
Flyweight fly = factory.factory(new Character('a'));
//以参量方式传入一个外蕴状态
fly.operation("First Call");
//向享元工厂对象请求一个内蕴状态为‘b’的享元对象
fly = factory.factory(new Character('b'));
//以参量方式传入一个外蕴状态
fly.operation("Second Call");
fly = factory.factory(new Character('a'));
fly.operation("Third Call");
factory.checkFlyweight();
}
}
虽然上面申请了三个享元对象,但是实际上创建的享元对象只有两个,这就是共享的含义。