享元模式
定义
享元模式(FlyWeight),运用共享技术有效的支持大量细粒度的对象。
享元模式的定义为我们提出了两个要求:细粒度和共享对象。我们知道分配太多的对象到应用程序中将有损程序的性能,同时还容易造成内存溢出,要避免这种情况,用到的就是共享技术,这里就需要提到内部状态和外部状态了。
因为要求细粒度对象,所以不可避免地会使对象数量多且性质相近,此时我们就将这些对象的信息分为两个部分:内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部并且不会随环境的改变而改变;外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
我们举一个最简单的例子,棋牌类游戏大家都有玩过吧,比如说说围棋和跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色略多一点,但也是不太变化的,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,我们落子嘛,落子颜色是定的,但位置是变化的,所以方位坐标就是棋子的外部状态。
优点
大大减少了对象的创建,降低了程序内存的占用,提高效率
缺点
提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变
使用场景
如果一个应用程序使用了大量的对象,而这些对象造成了很大的存储开销的时候就可以考虑是否可以使用享元模式。
例如,如果发现某个对象的生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享大幅度单个实例的数目。
UML类图:
代码实现:
public abstract class Flyweight {
private String intrinsic;
protected final String extrinsic;
public Flyweight(String extrinsic){
this.extrinsic = extrinsic;
}
public abstract void operate();
public String getIntrinsic(){
return intrinsic;
}
public void setIntrinsic(String intrinsic){
this.intrinsic = intrinsic;
}
}
public class ConcreteFlyweight1 extends Flyweight {
public ConcreteFlyweight1(String extrinsic) {
super(extrinsic);
// TODO Auto-generated constructor stub
}
@Override
public void operate() {
// TODO Auto-generated method stub
}
}
public class ConcreteFlyweight2 extends Flyweight {
public ConcreteFlyweight2(String extrinsic) {
super(extrinsic);
// TODO Auto-generated constructor stub
}
@Override
public void operate() {
// TODO Auto-generated method stub
}
}
public class FlyweightFactory {
private static HashMap<String,Flyweight> pool = new HashMap<String,Flyweight>();
public static Flyweight getFlyweight(String Extrinsic){
Flyweight flyweight = null;
if(pool.containsKey(Extrinsic)){
flyweight = pool.get(Extrinsic);
}else{
flyweight = new ConcreteFlyweight1(Extrinsic);
pool.put(Extrinsic, flyweight);
}
return flyweight;
}
}