zoukankan      html  css  js  c++  java
  • 设计模式——享元模式

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

    享元对象的所有状态分成两类:
      享元对象的第一类状态称为内蕴状态(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

  • 相关阅读:
    613. Shortest Distance in a Line
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    180. Consecutive Numbers
    612. Shortest Distance in a Plane
    178. Rank Scores
    177. Nth Highest Salary
    610. Triangle Judgement
    二维气泡弹窗
    jQuery触发a标签的click事件和原生javascript的区别
  • 原文地址:https://www.cnblogs.com/hpuCode/p/5408708.html
Copyright © 2011-2022 走看看