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)。

原文地址:https://www.cnblogs.com/pushudepu/p/6035388.html