设计模式——享元模式

  享元模式就是通过使用共享的方式,达到高效地支持大量的细粒度对象。它的目的就是节省占用的空间资源,从而实现系统性能的改善。

享元对象的所有状态分成两类:
  享元对象的第一类状态称为内蕴状态(Internal State)。它不会随环境改变而改变,存储在享元对象内部,因此内蕴状态是可以共享的,对于任何一个享元对象来讲,它的值是完全相同的。
  享元对象的第二类状态称为外蕴状态(External State)。它会随环境的改变而改变,因此是不可以共享的状态,对于不同的享元对象来讲,它的值可能是不同的。享元对象的外蕴状态必须由客户端保存,在享元对象被创建之后,需要使用的时候再传入到享元对象内部。

实现要素:
抽象享元类(Flyweight):它是所有具体享元类的超类。为这些类规定出需要实现的公共接口,那些需要外蕴状态的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
具体享元类(ConcreteFlyweight):具体享元类实现了抽象享元类所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元类又称为单纯具体享元类,因为复合享元类是由单纯具体享元角色通过复合而成的。
具体复合享元类(ConcreteCompositeFlyweight):复合享元类,又叫做不能共享的享元类。一个复合享元对象是由多个单享元对象组成,这些组成的对象是可以共享的,但是复合享元类本身并不能共享。
享元工厂类(FlyweightFactoiy):享元工厂类负责创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。

适用性:
  1、一个系统中存在着大量的细粒度对象;
  2、这些细粒度对象耗费了大量的内存。
  3、这些细粒度对象的状态中的大部分都可以外部化;
  4、这些细粒度对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。
  5、软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。

优点

  在于它大幅度地降低内存中对象的数量。

缺点

  1、享元模式为了使对象可以共享,它需要将部分状态外部化,这使得系统的逻辑变得复杂。
  2、享元模式将享元对象的部分状态外部化,而读取外部状态使得运行时间会有所加长。

总结

  满足以上的这些条件的系统可以使用享元对象。最后,使用享元模式需要维护一个记录了系统已有的所有享元的哈希表,也称之为对象池,而这也需要耗费一定的资源。因此,应当在有足够多的享元实例可供共享时才值得使用享元模式。如果只能够节省百八十个对象的话,还是没有必要引入享元模式的,毕竟性价比不高。

实现

  在网上看到的例子几乎都是举的是关于字母的那个例子。这里就接着造人以后造工具来进行实现。类图如下:

ITool(享元接口)定义:

package com.lidaming.design13.flyweight;
/**
 * 享元接口
 * @author admin
 *
 */
public interface ITool {
    void produce(String ext);
}
View Code

ConcreteTool具体工具类(单纯享元类)实现:

package com.lidaming.design13.flyweight;

public class ConcreteTool implements ITool {
    private String name;

    public ConcreteTool(String intenal) {
        this.name = intenal;
    }

    public void produce(String ext) {
        System.out.println("flyweight intenal:" + this.name);
        System.out.println("flyweight ext:" + ext);
    }

}
View Code

ConcreteCompositeTool复合工具类(复合享元类)实现:

package com.lidaming.design13.flyweight;

import java.util.HashMap;

public class ConcreteCompositeTool implements ITool {

    HashMap<String, ITool> tools = new HashMap<String, ITool>();

    public void add(String key, ITool tool) {
        tools.put(key, tool);
    }

    public void produce(String ext) {
        ITool tool = null;
        for (String item : tools.keySet()) {
            tool = tools.get(item);
            tool.produce(ext);
        }
    }

}
View Code

ToolFactory工具工厂类实现:

package com.lidaming.design13.flyweight;

import java.util.HashMap;
import java.util.List;

public class ToolFactory {
    HashMap<String, ITool> tools = new HashMap<String, ITool>();

    /**
     * 组合享元类
     * 
     * @param compositeNames
     * @return
     */
    public ITool factory(List<String> compositeNames) {
        ConcreteCompositeTool compositeTool = new ConcreteCompositeTool();
        for (String item : compositeNames) {
            compositeTool.add(item, factory(item));
        }
        return compositeTool;
    }

    /**
     * 单纯享元方法
     * 
     * @param intenal
     * @return
     */
    public ITool factory(String intenal) {
        ITool tool = tools.get(intenal);
        if (tool == null) {
            tool = new ConcreteTool(intenal);
            tools.put(intenal, tool);
        }
        return tool;
    }

}
View Code

场景类实现:

package com.lidaming.design13.flyweight;

import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
        List<String> compositeNames = new ArrayList<String>();
        compositeNames.add("a");
        compositeNames.add("b");
        compositeNames.add("c");
        compositeNames.add("d");

        ToolFactory toolFactory = new ToolFactory();
        ITool compositeTool2 = toolFactory.factory(compositeNames);
        ITool compositeTool1 = toolFactory.factory(compositeNames);
        compositeTool1.produce("ddd");
        
        
        ITool tool1 = toolFactory.factory("e");
        ITool tool2 = toolFactory.factory("e");
        System.out.println("-----------------");
        System.out.println("组合享元类能否共享:" + (compositeTool1 == compositeTool2));
        System.out.println("单纯享元类能否共享:" + (tool1 == tool2));

    }
}
View Code

 

参考

http://blog.csdn.net/wanghao72214/article/details/4046182
http://www.cnblogs.com/java-my-life/archive/2012/04/26/2468499.html

 

posted @ 2016-04-19 16:25  无头咸鱼  阅读(275)  评论(0编辑  收藏  举报