享元模式


享元模式

  • 享元模式:是一种重要的池技术的实现方式,使用共享对象可有效地支持大量的细粒度的对象。
  • 享元模式的定义提出了两个要求:细粒度的对象和共享对象,分配太多的对象到应用程序当中去将有损程序的性能,而且还容易造成内存溢出,通过享元模式的共享对象的技术来解决这些问题。首先我们先了解一下对象的内部状态(intrinsic)和外部状态(extrinsic)。
    • 内部状态:对象可共享出来的信息,存储在享元对象的内部并且不会随环境改变而改变,作为一个对象的动态附加信息,不必直接存储在具体某个对象中。
    • 外部状态:对象得以依赖的一个标记,随环境的改变而改变、不可共享的状态,是一批对象的统一标识,是唯一的一个索引值。
  • 有了对象的两种状态,我们来看一下享元模式的通用类图:

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 this.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 FlyweightFactory {
    private static HashMap<String, Flyweight> flyWeights = new HashMap<String, Flyweight>();
    public static Flyweight getFlyweight(String key){
        Flyweight flyweight = null;
        if(flyWeights.containsKey(key)){
            flyweight = flyWeights.get(key);
        }else{
            //根据外部状态创建享元对象
            flyweight = new ConcreteFlyweight1(key);
            //将享元对象放到池中
            flyWeights.put(key, flyweight);
        }
        return flyweight;
    }
}
View Code
享元模式的优缺点

    享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但同时也提高了系统的复杂性,需要分离出外部状态和内部状态,而外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统逻辑混乱。

享元模式的使用场景
  • 系统中存在大量的相似对象;
  • 细粒度的对象具备较近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;
  • 需要缓冲池的场景。
享元模式的扩展
  • 线程安全问题,当多个线程同时从对象缓冲池中取对象,并对对象的内部状态进行修改时,可能会造成线程的不安全。
public class MultiThread extends Thread{
    private Flyweight flyweight;
    private String intrinsic;
    public MultiThread(Flyweight flyweight){
        this.flyweight = flyweight;
        this.intrinsic = flyweight.getIntrinsic();
    }
    public void run(){
        String intrinsic = flyweight.getIntrinsic();
        if(!intrinsic.equalsIgnoreCase(this.intrinsic)){
            System.out.print("线程不安全......");
            System.out.println(this.intrinsic + "     " + intrinsic);
        }
    }
}

public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Flyweight flyweight = FlyweightFactory.getFlyweight("123");
        while(true){
            flyweight.setIntrinsic("intrinsic1");
            new MultiThread(flyweight).start();
            flyweight.setIntrinsic("intrinsic2");
            new MultiThread(flyweight).start();
        }
    }
}
View Code
  • 性能问题,尽量使用Java基本类型作为外部状态(即为key),如果自定义对象作为外部状态会降低系统执行的效率。
posted @ 2016-11-29 16:57  best.lei  阅读(366)  评论(0编辑  收藏  举报