zoukankan      html  css  js  c++  java
  • GOF之原型模式

    依赖关系的倒置

    抽象不应该依赖与实现细节,实现细节应该依赖与抽象。

    -抽象A直接依赖与实现细节b                    -抽象A依赖与抽象B,实现细节b依赖与抽象B

    动机(Motivation)

    在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。

    如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

    意图(Intent)

    使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

    结构(Structure)

    代码实现:

     1 对应于Prototype
     2 public abstract class Actor
     3     {
     4         private string _name;
     5 
     6         public string Name
     7         {
     8             get { return _name; }
     9             set { _name = value; }
    10         }
    11         public abstract Actor Clone(string name);
    12         public abstract void Say();
    13     }
     1 对应于ConcretePrototype
     2 class ActorA:Actor
     3     {
     4         
     5         public override Actor Clone(string name)
     6         {
     7             Actor actor = (Actor)this.MemberwiseClone();
     8             actor.Name ="ActorA"+name;
     9             return actor;
    10         }
    11         public override void Say()
    12         {
    13             Console.WriteLine("ActorA is say hai");
    14         }
    15     }
    16 
    17     class ActorB : Actor
    18     {
    19 
    20         public override Actor Clone(string name)
    21         {
    22             Actor actor = (Actor)this.MemberwiseClone();
    23             actor.Name = "ActorB" + name;
    24             return actor;
    25         }
    26         public override void Say()
    27         {
    28             Console.WriteLine("ActorB is say hai");
    29         }
    30     }
     1 对应于Client
     2 class Manager
     3     {
     4         private Actor _actor;
     5 
     6         public Actor Actor
     7         {
     8             get { return _actor; }
     9             set { _actor = value; }
    10         }
    11         public Manager(Actor actor)
    12         {
    13             this.Actor = actor;
    14         }
    15         public void Operation()
    16         {
    17             Actor a1 = Actor.Clone("zs");
    18             Actor a2 = Actor.Clone("ls");
    19             a1.Say();
    20             a2.Say();
    21             Console.WriteLine(a1.Name+"     "+a2.Name);
    22             Console.WriteLine(object.ReferenceEquals(a1,a2));
    23         }
    24     }
    1 主函数的调用
    2  static void Main(string[] args)
    3         {
    4             Manager manager = new Manager(new ActorB());
    5             manager.Operation();
    6             Console.ReadKey();
    7         }

    由于调用Object的MemberwiseClone()实现的是浅拷贝,所以用序列化实现深拷贝

     1 通过序列化实现深拷贝
     2  //深拷贝
     3         public override Actor CloneDeep(string name)
     4         {
     5             Actor actor;
     6             //创建内存流
     7             using (MemoryStream ms = new MemoryStream())
     8             {
     9                 BinaryFormatter bf = new BinaryFormatter();
    10                 //序列化成流
    11                 bf.Serialize(ms,new ActorA());
    12                 ms.Seek(0, SeekOrigin.Begin);
    13                 //反序列化成对象
    14                 actor = (Actor)bf.Deserialize(ms);
    15             }
    16             actor.Name = name;
    17             return actor;
    18         }

    Prototype模式的几个要点:

    Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。

    Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活的动态创建“拥有某些稳定接口”的新对象--所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断的Clone。

    Prototype模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。

    有关创建型模式的讨论:

    Singleton模式解决的是实体对象个数的问题。除了Singleton之外,其他创建型模式解决的都是new所带来的耦合关系。

    Factory Method, Abstract Factory, Builder都需要一个额外的工厂类来负责实例化“易变对象”,而Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”。

    如果遇到“易变类”,起初的设计通常从Factory Method开始,当遇到更多的复杂变化时,在考虑重构为其他三种工厂模式(Abstract Factory,Builder,Singleton)。

  • 相关阅读:
    HTTP Server
    分享:uSTL 2.0 发布,STL 标准模板库
    Boost.Asio和ACE之间关于Socket编程的比较
    使用BOOST实现简单的HTTP网页下载
    HTTP Client
    轩辕高端IT培训中心系昆山轩辕软件技术有限公司旗下的IT培训部门
    分享:链表实现的队列
    镕、喆、冇用五笔为何打不出来,在此向各位好友请教! 已回答 搜搜问问
    第一讲 Linux 编程入门与基本编程工具的使用
    C++03:使用Boost-用Asio实现简易Echo Server
  • 原文地址:https://www.cnblogs.com/pushudepu/p/6035388.html
Copyright © 2011-2022 走看看