Java设计模式 —— 享元模式(Flyweight)
Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。
定义
享元模式:运用共享技术有效地支持大量细粒度的对象。
特征:
- 采用一个共享来避免大量拥有相同内容对象的创建开销
- 关键是区分内蕴状态(Internal State)和外蕴状态(External State)
内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的。
外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。- 享元模式是池技术的重要实现方式,String常量池、数据库连接池、缓冲池等等
代码实现
抽象享元角色类
public interface Flyweight {
//一个示意性方法,参数state是外蕴状态
public void operation(String state);
}
具体享元角色类 ConcreteFlyweight 有一个内蕴状态,在本例中一个 Character 类型的 intrinsicState 属性代表,它的值应当在享元对象被创建时赋予。所有的内蕴状态在对象创建之后,就不会再改变了。
如果一个享元对象有外蕴状态的话,所有的外部状态都必须存储在客户端,在使用享元对象时,再由客户端传入享元对象。这里只有一个外蕴状态,operation() 方法的参数state就是由外部传入的外蕴状态。
public class ConcreteFlyweight implements 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("Intrinsic State = " + this.intrinsicState);
System.out.println("Extrinsic State = " + state);
}
}
享元工厂角色类,必须指出的是,客户端不可以直接将具体享元类实例化,而必须通过一个工厂对象,利用一个factory()方法得到享元对象。一般而言,享元工厂对象在整个系统中只有一个,因此也可以使用单例模式。
当客户端需要单纯享元对象的时候,需要调用享元工厂的 factory() 方法,并传入所需的单纯享元对象的内蕴状态,由工厂方法产生所需要的享元对象。
public class FlyweightFactory {
private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();
public Flyweight factory(Character state){
//先从缓存中查找对象
Flyweight fly = files.get(state);
if(fly == null){
//如果对象不存在则创建一个新的Flyweight对象
fly = new ConcreteFlyweight(state);
//把这个新的Flyweight对象添加到缓存中
files.put(state, fly);
}
return fly;
}
}
客户端类
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
FlyweightFactory factory = new FlyweightFactory();
Flyweight fly = factory.factory(new Character('a'));
fly.operation("First Call");
fly = factory.factory(new Character('b'));
fly.operation("Second Call");
fly = factory.factory(new Character('a'));
fly.operation("Third Call");
}
}
虽然客户端申请了三个享元对象,但是实际创建的享元对象只有两个,这就是共享的含义。
亨元模式使用问题
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
Android中亨元模式
Java String常量池
测试demo:
String m = "hello,world";
String n = "hello,world";
String u = new String(m);
String v = new String("hello,world");
System.out.println(m == n); //true
System.out.println(m == u); //false
System.out.println(m == v); //false
System.out.println(u == v); //false
结论:
m和n是同一个对象
m,u,v都是不同的对象
m,u,v,n但都使用了同样的字符数组,并且用equal判断的话也会返回true
感谢
segmentfault: 亨元模式
菜鸟教程:亨元模式
百度百科:亨元模式
博客园:
《JAVA与模式》之享元模式
简说设计模式——享元模式
W3Cschool:享元模式