创建型模式:Prototype 原型模式

                                                         创建型模式:Prototype 原型模式

1、依赖关系的倒置
  1)抽象不应该依赖于实现细节,实现细节应该依赖于抽象。
  2)不好的做法:抽象A直接依赖于实现细节B
  3)oo做法:抽象A依赖于抽象B,实现细节b依赖于抽现B
 
2、动机(Motivation)
  1)在软件系统中,经常面临着“某此结构复杂的对象”的创建工作,由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
  2)如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

3、意图(Intent)
  使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
                           ——《设计模式》GoF
                         
4、实例:游戏场景,创建各种兵种(魂斗锣)
//游戏系统,运行游戏时创建兵种
public class GameSystem
{
  /*不好的做法,因为这里是变化的,抽像不应依赖实现细节
  public static void Run()
  {
    //地上走的小兵(不会飞的),需要五个
    NormalActor normalActor1 = new NormalActorA();
    NormalActor normalActor2 = new NormalActorA();
    NormalActor normalActor3 = new NormalActorA();
    NormalActor normalActor4 = new NormalActorA();
    NormalActor normalActor5 = new NormalActorA();
   
    //会飞的小兵,需要二个
    FlyActor FlyActor1 = new FlyActorA();
    FlyActor FlyActor2 = new FlyActorA();
   
    //潜水的小兵,需要二个
    WaterActor WaterActor1 = new WaterActorA();
    WaterActor WaterActor2 = new WaterActorA();   
  }*/
 
  public static void Run(NormalActor normalActor,
      FlyActor flyActor, WaterActor waterActor)
  {
    NormalActor normalActor1 = normalActor.Clone();
    NormalActor normalActor2 = normalActor.Clone();
    NormalActor normalActor3 = normalActor.Clone();
    NormalActor normalActor4 = normalActor.Clone();
    NormalActor normalActor5 = normalActor.Clone();
   
    FlyActor FlyActor1 = FlyActor.Clone();
    FlyActor FlyActor2 = FlyActor.Clone();
   
    WaterActor WaterActor1 = WaterActor.Clone();
    WaterActor WaterActor2 = WaterActor.Clone();
  }
}

//抽象类都要提供一个克隆自己的方法
[Serializable]
public abstract class NormalActor
{
  public abstract NormalActor Clone();
}
//抽象类
[Serializable]
public abstract class FlyActor
{
  public abstract FlyActor Clone();
}
//抽象类
[Serializable]
public abstract class WaterActor
{
  public abstract WaterActor Clone();
}

//用序列化方式实现深拷贝所需的命名空间
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
//步兵A
[Serializable]
public class NormalActorA : NormalActor
{
  public override NormalActor Clone()
  {
    //MemberwiseClone方法是根Object目根下受保护的方法
    //该方法是按成员拷贝的方式,是个浅拷贝
    //浅拷贝会完全拷贝值类型,而只拷贝引用类型的地址值,
    //它们指向相同的引用,因此克隆出的对象与原型有共享部分
    //一般都会使用到深拷贝,深拷贝会完全拷贝全部数据类型
    return (NormalActorA)this.MemberwiseClone();
   
    /*下面方法实现深拷贝
    MemoryStream memoryStream = new MemoryStream();
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    //序列化
    binaryFormatter.Serialize(memoryStream, this);
    memoryStream.Position = 0;
    //反序列化
    return (NormalActor)formatter.Deserialize(memoryStream);*/
  }
}
//步兵B
[Serializable]
public class NormalActorB : NormalActor
{
  public override NormalActor Clone()
  {
    return (NormalActorB)this.MemberwiseClone();
  }
}

//飞兵A
[Serializable]
public class FlyActorA : FlyActor
{
  public override FlyActor Clone()
  {
    return (FlyActorA)this.MemberwiseClone();
  }
}
//飞兵B
[Serializable]
public class FlyActorB : FlyActor
{
  public override FlyActor Clone()
  {
    return (FlyActorB)this.MemberwiseClone();
  }
}

//水兵A
[Serializable]
public class WaterActorA : WaterActor
{
  public override WaterActor Clone()
  {
    return (WaterActorA)this.MemberwiseClone();
  }
}
//水兵B
[Serializable]
public class WaterActorB : WaterActor
{
  public override WaterActor Clone()
  {
    return (WaterActorB)this.MemberwiseClone();
  }
}

//客户程序
class App
{
  public static void Main()
  {
    GameSystem gameSystem = new GameSystem();
    gameSyste.Run(new NormalActor(), new FlyActorB(), new WaterActorA());
  }
}

5、Prototype模式的几个要点
  1)Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。
  2)Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新类的对象(即原型),然后在任何需要的地方不断地Clone。
  3)Prototype模式中的Clone方法可以利用.NET中的Object的MemberwiseClone()方法或者序列化来实现深拷贝。
 
6、有关创建型模式的讨论
  1)Singleton模式解决的是实体对象个数的问题。除了Singleton之外,其他创建型模式解决的都是new所带来的耦合关系。
  2)Factory Method,Abstract Factory,Builder都需要一个额外的工厂类来负责实例化“易变对象”,而Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”。
  3)如果遇到“易变类”,起初设计通常从Factory Method开始,当遇到更多的复杂变化时,再考虑重构为其他三种工厂模式(Abstract Factory,Builder,Prototype)。

你可能感兴趣的:(创建型模式:Prototype 原型模式)