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();
}
}ide
//抽象类都要提供一个克隆本身的方法
[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();
}ui
//用序列化方式实现深拷贝所需的命名空间
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();
}
}this
//飞兵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();
}
}orm
//客户程序
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)。接口