四川适合种植象草吗?

小说:四川适合种植象草吗?作者:安顺安更新时间:2019-05-23字数:45056

“有何不敢?”黄昏晓傲然说道:“不过既然是赌,你我就要有些赌注,若是本座赢了,你给输给本座什么?”

金边黄杨哪里有?

“不用了,你都已经要死的人了,还需要向上面要求什么支援啊”一道冷峻的声音在他的耳畔响起。
“以夫君的聪明才智!”林花雨的声音在这片桃林之中不断的回荡:“肯定是能够从中走出来的。我虽然是知道怎么走,也不会告诉你的!一旦告诉了你,我师父势必是要更改其中的阵势,到时候你还得从头来过!”

龙一带着手下快步走出,唐牛吐了一口吐沫,“什么东西,当初小人得志的那副模样,现在终于知道大人的厉害。”

一、引言

   今天我们要讲【结构型】设计模式的第六个模式,该模式是【享元模式】,英文名称是:Flyweight Pattern。还是老套路,先从名字上来看看。“享元”是不是可以这样理解,共享“单元”,单元是什么呢,举例说明,对于图形而言就是图元,对于英文来说就只26个英文字母,对于汉语来说就是每个汉字,也可以这样理解“元”,构成事物的最小单元,这些单元如果大量、且重复出现,可以缓存重复出现的单元,达到节省内存的目的,换句说法就是享元是为了节省空间,对于计算机而言就是内存。面向对象很好地解决了系统抽象性的问题(系统抽象性指把系统里面的事物写成类,类可以实例化成为对象,用对象和对象之间的关系来设计系统),在大多数情况下,这样做是不会损及系统的性能的。但是,在某些特殊的应用中,由于对象的数量太大,并且这些大量的对象中有很多是重复的,如果每个对象都单独的创建(C#的语法是new)出来,会给系统带来难以承受的内存开销。比如图形应用中的图元等对象、字处理应用中的字符对象等。

二、享元模式的详细介绍

2.1、动机(Motivate)

   在软件系统中,采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?

2.2、意图(Intent)

   运用共享技术有效地支持大量细粒度的对象。                                             ——《设计模式》GoF

2.3、结构图

       i

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

    (2)、具体享元角色(ConcreteFlyweight):实现抽象享元角色所规定的接口。如果有内部状态的话,可以在类内部定义。

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

    (4)、客户端角色(Client):本角色需要存储所有享元对象的外部状态。

2.5、享元模式的具体实现

    说起“享元模式”,我这里有一个很好的场景可以进行说明。我们知道在战斗的游戏场景中,会有很多战士,基本上战士都是差不多的,小区别战士忽略,最大的区别就是拿的武器不同而已。在大型的战争游戏中,会有大量的士兵出来战斗,我们写程序的时候就可以用“享元”来解决大量战士的情况。

  1 namespace 享元模式的实现
  2 {
  3     /// <summary>
  4     /// 享元模式不是很难,但是有些状态需要单独处理,以下就是该模式的C#实现,有些辅助类,大家应该看得出吧,别混了。
  5     /// </summary>
  6     class Client
  7     {
  8         static void Main(string[] args)
  9         {
 10             //比如,我们现在需要10000个一般士兵,只需这样
 11             SoldierFactory factory=new SoldierFactory();
 12             AK47 ak47=new AK47();
 13             for(int i=0;i<10000;i++)
 14             {
 15               factory.GetSoldier("士兵"+(i+1),ak47,SoldierType.Normal);
 16             }
 17             //我们有这么多的士兵,但是使用的内存不是很多,因为我们缓存了。
 18             Console.Read();
 19         }
 20     }
 21  
 22     //这些是辅助类型
 23     public enum SoldierType
 24     {
 25        Normal,
 26        Water
 27     }
 28 
 29     //该类型就是抽象战士Soldier--该类型相当于抽象享元角色
 30     public abstract class Soldier
 31     {
 32         //通过构造函数初始化士兵的名称
 33         protected Soldier(string name)
 34         {
 35            this.Name=name;
 36         }
 37         
 38         //士兵的名字
 39         publi string Name{get;private set;}
 40 
 41         //可以传入不同的武器就用不同的活力---该方法相当于抽象Flyweight的Operation方法
 42         public abstract void Fight(Weapen weapen);
 43     }
 44  
 45     //一般类型的战士,武器就是步枪---相当于具体的Flyweight角色
 46     public sealed class NormalSoldier:Soldier
 47     {
 48         //通过构造函数初始化士兵的名称
 49         public NormalSoldier(string name):base(name){}
 50 
 51         //执行享元的方法---就是Flyweight类型的Operation方法
 52         public override void Fight(Weapen weapen)
 53         {
 54             weapen.Fire("在陆地执行击毙任务");
 55         }
 56     }
 57  
 58     //这是海军陆战队队员,武器精良----相当于具体的Flyweight角色
 59     public sealed class WaterSoldier:Soldier
 60     {
 61         //通过构造函数初始化士兵的名称
 62         public WaterSoldier(string name):base(name){}
 63 
 64         //执行享元的方法---就是Flyweight类型的Operation方法
 65         public override void Fight(Weapen weapen)
 66         {
 67             weapen.Fire("在海中执行击毙任务");
 68         }
 69     }
 70 
 71    //此类型和享元没太大关系,可以算是享元对象的状态吧,需要从外部定义
 72    public abstract class Weapen
 73    {
 74       public abstract void Fire(string jobName);
 75    }
 76 
 77    //此类型和享元没太大关系,可以算是享元对象的状态吧,需要从外部定义
 78    public sealed class AK47
 79    {
 80       public override void Fire(string jobName)
 81       {
 82          Console.WriteLine(jobName);
 83       }
 84    }
 85 
 86    //该类型相当于是享元的工厂---相当于FlyweightFactory类型
 87    public sealed class SoldierFactory
 88    {
 89       private IList<Soldier> soldiers;
 90 
 91       static SoldierFactory()
 92       {
 93          soldiers=new List<Soldier>();
 94       }
 95 
 96       Soldier mySoldier=null;
 97       //因为我这里有两种士兵,所以在这里可以增加另外一个参数,士兵类型,原模式里面没有,
 98       public Soldier GetSoldier(string name,Weapen weapen,SoldierType soldierType)
 99       {
100          foreach(Soldier soldier in soldiers)
101          {
102             if(string.Compare(soldier.Name,name,true)==0)
103             {
104                mySoldier=soldier;
105                return mySoldier;
106             }
107          }
108          //我们这里就任务名称是唯一的
109          if(soldierType==Normal)
110          {
111             mySoldier=new NormalSoldier(weapen);
112           }
113           else
114           {
115             mySoldier=new WaterSoldier(weapen);
116           }
117 
118           soldiers.Add(mySoldier);
119           return mySoldier;
120       }
121    }
122 }


   这个模式很简单,就话不多说了。

三、享元模式的实现要点:
    
    面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。

    Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。

 对象的数量太大从而导致对象内存开销加大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。

    优点

      1、享元模式的优点在于它能够极大的减少系统中对象的个数。

      2、享元模式由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境被共享。

    缺点

      1、由于享元模式需要区分外部状态和内部状态,使得应用程序在某种程度上来说更加复杂化了。

      2、为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变

四、.NET 中享元模式的实现

    .NET在C#中有一个Code Behind机制,它表面有一个aspx文件,背后又有一个cs文件,它的编译过程实际上会把aspx文件解析成C#文件,然后编译成dll,在这个过程中,我们在aspx中写的任何html代码都会转化为literal control,literal control是一个一般的文本控件,它就表示html标记。当这些标记有一样的时候,构建控件树的时候就会用到Flyweight模式.

  它的应用并不是那么平凡,只有在效率空间确实不高的时候我们才用它。

五、总结

    刚开始接触这个模式的时候,感觉这个模式不是特别难,在我们编码的过程中也有涉及,但是在学习的过程中也走了不少弯路,任何设计模式都有他特定的使用场景,小心误用。这个模式在业务系统中相对而言使用的并不多,在类似游戏场景中、字符处理等系统用的比较多。还是老话,通过迭代来使用模式,别为了模式而模式。今天就到这里,以后继续。

编辑:建董

发布:2019-05-23 13:45:27

当前文章:http://scycxh.com/news_55302.html

云南可以种植碧桃吗? 红叶石楠树批发去哪里? 最大面积紫藤基地哪里有? 常用的藤本月季规格大全,告诉什么规格性价比最高 剪股颖草坪有多高? 草坪四季青种子多长时间发芽? 草坪每亩需草籽多少斤? 虞美人播种的时间是几月?

42866 50321 68405 22176 57172 22326 52907 99651 76293 56629 17422 13162 71978 11704 44473 94716 97829 27660 38425 84125

我要说两句: (0人参与)

发布