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