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

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、总结

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

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

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

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

原文地址:https://www.cnblogs.com/shun-gege/p/7510783.html