设计模式:享元模式

十. 享元模式
整理自 《java与模式》阎宏编著


1.意图:
    运用共享技术有效地支持大量细粒度的对象。

2.类图:
      单纯享元模式:

        

      复合享元模式:
      
         

3.原理:
      享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。
      一个内蕴状态是存储在享元对象内部的,并且不会随环境改变而有所不同的。因此,一个享元可以具有内蕴状态并可以共享。
      一个外蕴状态是随环境改变而改变的,不可以共享状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传到享元对象内部。
      外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。所有的内蕴状态在对象创建完后就不可再改变。



4.特征:

    单纯享元模式:
    抽象享元角色:所有的具体享元类的超类,规定出需要实现的公共接口。那些需要外蕴状态的操作可以通过方法的参数传入。
    具体享元角色:实现抽象享元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。
    享元工厂角:负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象时,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果有,享元工厂就提供这个已经有的享元对象,如果没有,享元工厂创建一个适当的享元对象。
    客户端角色:需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外蕴状态。

  复合享元模式:
    抽象享元角色:所有的具体享元类的超类,规定出需要实现的公共接口。那些需要外蕴状态的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
    具体享元角色:实现抽象享元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。复合享元角色是由具体享元角色通过复合而成。
    复合享元角色:复合享元角色所代表的对象是不可以共享的,但是可以分解成多个可以共享的具体享元角色。
    享元工厂角:负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象时,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果有,享元工厂就提供这个已经有的享元对象,如果没有,享元工厂创建一个适当的享元对象。
    客户端角色:需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外蕴状态。


5.说明:
6.使用案例:
      Java中的String对象。
       在编辑器系统中,每个字母做成一个享元对象,内蕴状态就是这个字母,而字母在文本中的位置和风格就是外蕴状态。

7.代码:
     单纯享元模式:

   // Client.java

   public class Client

   {      

       private FlyweightFactory flyweightFactory = null;  

       public Client()

       {

          flyweightFactory = new FlyweightFactory();

       }

   }

   // FlyweightFactory.java
   public class FlyweightFactory

   {

        private flyweight.Flyweight lnkFlyweight;

     private HashMap flyweightPools;



        public FlyweightFactory()

        {

            flyweightPools = new HashMap();

        }



        //客户端不能直接实例化享元类,必须通过工厂类。

        public Flyweight getFlyweight(Object key)

        {

            if (flyweightPools.containsKey(key))

            {

                 return (Flyweight) flyweightPools.get(key);

            }

            else

            {

                 Flyweight newFlyweight = new ConcreteFlyweight(key);

                 flyweightPools.put(key, newFlyweight);

                 return newFlyweight;

            }

        }

   }

   // Flyweight.java

   public interface Flyweight

   {

        //一个示意性的方法,参数是外蕴状态

        void sampleOperation(Object extrinsicState);

   }

   // ConcreteFlyweight.java

   public class ConcreteFlyweight implements Flyweight

   {

       private Object  intrisnicState;

 

       //构造函数,内蕴状态作为参数传入,

        public ConcreteFlyweight(Object intrisnicState)

        {

            // initialize internal state

            this.intrisnicState = intrisnicState;

        } 



        //外蕴状态作为参数传入,修改了方法的行为,不改变内蕴状态。

        public void sampleOperation(Object extrinsicState)

        {

             //....

        }

   }

猜你喜欢

转载自xiangyuan.iteye.com/blog/2076057
今日推荐