设计模式学习总结-享元模式(Flyweight Method)

问题:
在面向对象的设计中和开发中,经常会遇到,同一类型的对象(由同一个class new出)会在不同的场景中出现多次,可是由于应用场景不同,他们的状态(属性值)又有所不同,但是他们的大多数属性又都是相同的,我们需要在不同的应用场景中创建大量具有不同状态的对象,然而大量的对象会造成很大的系统存储开销,以及对象的创建时的性能开销。
定义:

享元模式(又叫:轻量级模式)是一种结构型模式,运用共享技术有效地支持大量细粒度的对象。

意图:
抽出多个同一对象在不同应用场景中的共同状态(intrinsic,在不同的应用场景中相对不变的),封装在一个可以被共享的元类中(Concrete Flyweight),并提供一个修改需要变化状态的访问接口,用于在不同场景中,修改不被共享的外部状态(extrinsic),Flyweight Factory拥有一个管理、存储对象的“仓库”(或者叫对象池),当接收到客户端请求时会遍历对象池中的对象,如果已经存在则直接返回给Client,否则创建一个新的对象并将这个对象加入到池中然后返回给客户端,从而减少了大量的对象创建工作。

参与者:
•抽象享元(Flyweight)角色:

此角色是所有的具体享元类的基类,为这些类规定出需要实现的公共接口。那些需要外部状态(extrinsic)的操作可以通过调用享元方法以参数形式传入。
•具体享元(Concrete Flyweight)角色:

实现抽象享元角色所规定的接口。如果有内部状态(intrinsic)的话,必须负责为内部状态(intrinsic)提供存储空间。享元对象的内部状态(intrinsic)必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。
•享元工厂(Flyweight Factory)角色:

本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
•客户端(Client)角色:

本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外部状态(Extrinsic)。

UML:

设计模式学习总结-享元模式(Flyweight Method)_第1张图片


实例说明:

诺基亚手机工厂
有总部工厂生产,然后转给各个分公司贴牌上市

uml图如下:

 设计模式学习总结-享元模式(Flyweight Method)_第2张图片

代码:

///   <summary>
///  抽象享元(Flyweight)角色
///   </summary>
public  abstract  class PhoneModel
{

     //  共享元素
     public  string Name {  getset; }
     public  string Net {  getset; }
     public  string Size {  getset; }
     // 不共享状态的元素   
     protected  string ProductionPlace {  getset; }
     //  提供一个修改不共享状态修改的方法。
     public  abstract  void Change( string productionPlace);
}
///   <summary>
///  具体享元(Concrete Flyweight)角色
///   </summary>
public  class N8Object : PhoneModel
{
     public  N8Object()
    {
         this.Name =  " N8 ";
         this.Net =  " CDMA ";
         this.Size =  " 98*20*10 ";
    }
     public  override  void Change( string productionPlace)
    {
         this.ProductionPlace = productionPlace;
    }
}
///   <summary>
///  具体享元(Concrete Flyweight)角色
///   </summary>
public  class N9Object : PhoneModel
{
     public  N9Object()
    {
         this.Name =  " N9 ";
         this.Net =  " WCDMA ";
         this.Size =  " 100*20*10 ";
    }
     public  override  void Change( string productionPlace)
    {
         this.ProductionPlace = productionPlace;
        System.Console.WriteLine( " 已修改N9的产地为 " + productionPlace);
    }
}
///   <summary>
///  享元工厂(Flyweight Factory)角色
///   </summary>
public  class FlyweightFactory 
{
    Dictionary< string, PhoneModel> PhoneList =  new Dictionary< string, PhoneModel>();

     public PhoneModel GetPhoneObject( string name)
    {
         if (!PhoneList.ContainsKey(name))
        {
            PhoneModel phone =  null;
             switch (name)
            {
                 case  " N8 ":
                    phone =  new N8Object();  break;
                 case  " N9 ":
                    phone =  new N9Object();  break;
            }
            PhoneList.Add(name, phone);
        }
         return PhoneList[name];
    }
}
///   <summary>
///  客户端测试
///   </summary>
public  void DecoratorTest()
{
    FlyweightFactory factory =  new FlyweightFactory();
     var n8= factory.GetPhoneObject( " N8 ");
    n8.Change( " 新西兰 ");
}

优点:
•减少处理的对象数量,从而减少大量的对象存储开销,以及对象的创建时的性能开销。
缺点:
•需要由客户端维护对象的外部状态,如果外部状态的数据量大,传递、查找、计算会变得非常复杂。
适用场合:
•系统需要存在大量的对象而不同场景下的对象拥有大量的共享状态。
PS:
享元工厂中维护了享元实例的列表,同样也需要占用资源,所以如果享元的实例不是非常多的话(一个对象的应用场景比较少),不适合使用享元模式
如果对象拥有非常多的独立状态,比共享状态还要多不适合运用享元模式。因为维持大量的外部状态不但会使逻辑复杂而且并不能节约资源。

你可能感兴趣的:(设计模式学习总结-享元模式(Flyweight Method))