• 设计模式(十三)---享元模式


    1、简介

      享元模式是对象的结构模式,以共享的方式高效的支持大量的细粒度对象,也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。

      享元对象做到共享的关键是区分内蕴状态和外蕴状态

      1.1、内蕴状态:内蕴状态是存储在享元对象内部的,不会随环境改变而发生改变的。

      1.2、外蕴状态:外蕴状态是不可以共享的状态,需要由客户端保存,并在享元对象创建后,在需要的时候再传入到享元对象的内部,外蕴状态不可以影响内蕴状态,他们是互相独立的

    2、享元模式类图

      

    3、从上面类图可以看出,享元模式涉及以下几个角色

      3.1、抽象享元角色:此角色是所有具体享元类的超类,为这些类规定出需要实现的公共接口

      3.2、具体享元角色:实现抽象享元角色所规定的接口,享元对象的内蕴状态必须与所处的环境无关,从而使得享元对象可以在整个系统中共享。

      3.3、享元工厂角色:本角色负责创建和管理享元对象,本角色必须保证享元对象可以被系统合适的共享。

      3.4、测试客户端   :本角色需要维护一个对所有享元对象的引用,还需要自己维护所有享元对象的外蕴状态

    4、源代码

      4.1、抽象享元角色

    package FlyweightPattem;
    /**
     * ********************************************************  
    * @ClassName: Flyweight 
    * @Description: 抽象享元角色 
    **********************************************************
     */
    public abstract class Flyweight {
        public abstract  void  operation(String state);
    }

      4.2、具体享元角色

    package FlyweightPattem;
    /**
     * ********************************************************  
    * @ClassName: ConcreteFlyweight 
    * @Description: 具体享元角色
    **********************************************************
     */
    public class ConcreteFlyweight extends Flyweight{
        private Character intrinsicState = null;
        
        //构造器   将内蕴状态当作参数传入
        public ConcreteFlyweight(Character state) {
            this.intrinsicState = state;
        }
        /**
         * **********************************************************
        * @Title: operation 
        * @Description: 外蕴状态作为参数传入方法中,改变方法的行为
        *                 但是并不改变对象的内蕴状态
        * @param @param states    设定文件 
        * @return void    返回类型 
        * @throws 
        **********************************************************
         */
        @Override
        public void operation(String state) {
            System.out.println("
    intrinsicState = "
                                +intrinsicState+
                                " state = "+state);
            
        }
    
    }

      4.3、享元工厂角色

    package FlyweightPattem;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    /**
     * ********************************************************  
    * @ClassName: FlyweightFactory 
    * @Description:享元工厂 
    **********************************************************
     */
    public class FlyweightFactory {
            //这个map在这里 作为一个对象常量池来使用
            @SuppressWarnings("rawtypes")
            private HashMap files = new HashMap();
            private Flyweight inkFlyweight;
            
            public Flyweight factory(Character state){
                if(files.containsKey(state)){
                    return (Flyweight) files.get(state);
                }else{
                    Flyweight fly = new ConcreteFlyweight(state);
                    files.put(state, fly);
                    return fly;
                }
            }
            //检查打印的方法
            public void checkFlyweight(){
                Flyweight flyweight;
                int i= 0;
                System.out.println("
    ==========checkFlyweight()============");
                for(Iterator it = files.entrySet().iterator();it.hasNext();){
                    Map.Entry e = (Map.Entry) it.next();
                    System.out.println("item"+(++i)+":"+e.getKey());
                }
                System.out.println("==========checkFlyweight()============");
            }
    }

      4.4、测试客户端

    package FlyweightPattem;
    /**
     * ********************************************************  
    * @ClassName: FlyweightTest 
    * @Description: 享元模式测试客户端 
    **********************************************************
     */
    public class FlyweightTest {
    
        public static void main(String[] args) {
            //创建享元工厂对象
            FlyweightFactory factory = new FlyweightFactory();
            //调用工厂对象生成一个内蕴对象为a的享元对象
            Flyweight fly = factory.factory('a');
            //传入外蕴状态
            fly.operation("Frist Call");
            //调用工厂对象生成一个内蕴对象为b的享元对象
            fly = factory.factory('b');
            //传入外蕴状态
            fly.operation("second Call");
            //调用工厂对象生成一个内蕴对象为a的享元对象
            fly = factory.factory('a');
            //传入外蕴状态
            fly.operation("Third Call");
            //调用checkFlyweight方法  打印出所有独立的享元对象
            factory.checkFlyweight();
        }
    
    }

    5、测试,运行结果如下

    6、总结

      使用享元模式需要维护一个记录系统已有享元对象的表,这需要额外的消耗资源,所以,应当在有足够多的享元实例可以共享的时候才使用这个模式

      可以看出,享元模式的优点在于可以大幅度降低内存中对象的数量,但是,相应的付出的代价也很高,

      享元模式是系统变得更复杂,为了使对象可以共享,需要将一些状态外部化,从而使得逻辑变得非常复杂

      其次,外部化的状态,读取外部状态也需要消耗额外的资源。

  • 相关阅读:
    DSYMTools App Bug 分析工具
    Xcode dSYM 文件
    sqlserver数据库18456错误怎么解决?
    C#两个DataTable拷贝问题:该行已经属于另一个表的解决方法
    SNF微信公众号客户端演示-微信开发客户端能干什么
    sqlserver中创建链接服务器图解教程
    C#日期格式转换大全
    C#-MVC开发微信应用(8)--菜单管理的实现
    C#-MVC开发微信应用(7)--在管理系统中同步微信用户分组信息
    C#-MVC开发微信应用(6)--用户分组信息管理
  • 原文地址:https://www.cnblogs.com/shun-gege/p/7510783.html
Copyright © 2020-2023  润新知