享元模式

来源:互联网 发布:java年终总结 编辑:程序博客网 时间:2024/05/18 01:57

1,GoF对享元模式的描述是:运用共享技术有效地支持大量细粒度的对象。
Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用。也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。在Flyweight模式中,由于要产生各种各样的对象,所以在Flyweight(享元)模式中常出现Factory模式。Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个对象存储池(Flyweight Pool)来存放内部状态的对象。为了调用方便,FlyweightFactory类一般使用Singleton模式实现。Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。

Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况成立时使用Flyweight模式:
1 一个应用程序使用了大量的对象。
2 完全由于使用大量的对象,造成很大的存储开销。
3 对象的大多数状态都可以变为外部状态。
4 如果删除对象以外的状态那么可以用相对较少的共享对象取代很多组对象。
5 应用程序不依赖于对象标识。



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)

        {

             //....

        }

   }