本文中儘可能在一頁中可以簡單明瞭的說明各類經常使用建立類型的設計模式,儘可能寫的通俗易懂些(部分參照了其餘地方的經典示例),其餘類型設計模式將繼續更新奉上。c#
細節很重要,如下設計模式代碼中的類和方法中的修飾符個別省略掉使用類或者方法的默認修飾符,因此必須知道c#中默認的修飾符:類默認是internal,方法和嵌套類默認是private,構造函數顯式聲明的默認是private,不然系統幫忙生成的默認構造函數是public的;接口枚舉成員默認是public且不能顯式聲明,結構屬於值類型不能被繼承,因此其內部成員是private的。設計模式
代碼說明參照代碼中的註釋!安全
文章目錄:app
建立類型的模式ide
1)通常在應用中爲了線程安全考慮,都會使用雙重鎖模式處理,以下代碼:性能
//不推薦使用,這個反而是大多數教程裏的示例 public sealed class Singleton { //私有靜態變量 static Singleton instance=null; static readonly object padlock = new object(); //私有構造函數 Singleton() { } public static Singleton Instance { get { if (instance==null) { lock (padlock) { if (instance==null) { instance = new Singleton(); } } } return instance; } } }
2)以上實現不會確保在使用的時候再實例化(懶加載模式)且性能不佳,因此又有了如下實現:ui
//推薦使用,線程安全且實現懶加載 public sealed class Singleton { //私有構造函數,阻止自動生成的默認構造函數 Singleton() { } //提供全局訪問出口 public static Singleton Instance { get { return Nested.instance; } } //嵌套類,實現懶加載 class Nested { //顯示聲明爲靜態構造函數(不能有修飾符,調用類中的成員或者第一次實例化時僅執行一次),確保了嵌套類實例化在調用以後,因此實現了懶加載,並且也保證了性能。 static Nested() { } //初始化後將不能改變 internal static readonly Singleton instance = new Singleton(); } }
二、工廠方法模式(定義一個接口或者抽象基類用於建立對象,可是讓子類決定初始化哪一個類。工廠方法把一個類的初始化下放到子類。)this
工廠方法模式最大的有點就是利用面向對象的多態性,實現了對外開放訪問,封閉修改的開發封閉原則。如下是示例spa
public abstract class Fruit { public abstract void Print(); } /// <summary> /// 蘋果 /// </summary> public class Apple : Fruit { public override void Print() { Console.WriteLine("我是蘋果!"); } } /// <summary> /// 香蕉 /// </summary> public class Banana : Fruit { public override void Print() { Console.WriteLine("我是香蕉"); } } /// <summary> /// 抽象工廠類 /// </summary> public abstract class FruitFactory { // 工廠方法 public abstract Fruit CreateFruit(); } /// <summary> /// 蘋果的簡單工廠類 /// </summary> public class AppleFactory : FruitFactory { public override Fruit CreateFruit() { return new Apple(); } } /// <summary> /// 香蕉的簡單工廠類 /// </summary> public class BananaFactory : FruitFactory { public override Fruit CreateFruit() { return new Banana(); } } /// <summary> /// 客戶端調用 /// </summary> class Client { static void Main(string[] args) { // 工廠初始化,妙處就在這裏 工廠基類中的方法交由實現它的子類去處理建立的水果是蘋果仍是香蕉 FruitFactory _appleFactory = new AppleFactory(); FruitFactory _bananaFactory = new BananaFactory(); // 製做蘋果,這個水果簡單工廠作的是蘋果 Fruit appleInsane = _appleFactory.CreateFruit(); appleInsane.Print(); //製做香蕉 ,這個水果簡單工廠作的是香蕉 Fruit bananaInsane = _bananaFactory.CreateFruit(); bananaInsane.Print(); Console.Read(); } }
三、抽象工廠模式(爲一個產品族提供了統一的建立接口。當須要這個產品族的某一系列的時候,能夠從抽象工廠中選出相應的系列建立一個具體的工廠類。)
抽象工廠模式將具備同一主題特性的單獨的工廠封裝起來,它將一組對象的實現和使用分離開。好比以上的工廠方法模式中,一個水果簡單工廠只能建立一個類的示例,不能建立一系列主題的類的實例,因此纔有了抽象工廠模式來實現。如下是示例
//智能機接口 interface IDumb { string Name(); } //老式機接口 interface ISmart { string Name(); } //老式機產品類 class Asha : IDumb { public string Name() { return "Asha"; } } class Primo : IDumb { public string Name() { return "Guru"; } } //智能機產品 class Lumia : ISmart { public string Name() { return "Lumia"; } } class GalaxyS2 : ISmart { public string Name() { return "GalaxyS2"; } } /// <summary> /// 抽象工廠,跟IPhone不要緊,只是個接口 /// </summary> interface IPhoneFactory { ISmart GetSmart(); IDumb GetDumb(); } //建立工廠類,例子 三星生產蓋世智能機和primo老式機 class SamsungFactory : IPhoneFactory { public ISmart GetSmart() { return new GalaxyS2(); } public IDumb GetDumb() { return new Primo(); } } class NokiaFactory : IPhoneFactory { public ISmart GetSmart() { return new Lumia(); } public IDumb GetDumb() { return new Asha(); } } //客戶端調用 static void Main(string[] args) { IPhoneFactory SAMSUNGfactory=new SamsungFactory(); Console.WriteLine("Smart Phone: " + SAMSUNGfactory.GetSmart().Name() + "\nDumb Phone: " + SAMSUNGfactory.GetDumb().Name()); IPhoneFactory NOKIAfactory=new NokiaFactory(); Console.WriteLine("Smart Phone: " + NOKIAfactory.GetSmart().Name() + "\nDumb Phone: " + NOKIAfactory.GetDumb().Name()); }
四、原型模式(用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。)
這個模式的就是利用克隆多個原型副原本建立對象,好處就是一樣的對象實例不用老是new,節省內存
/// <summary> /// 原型 /// </summary> public abstract class Prototype { public string Id { get; set; } public Prototype(string id) { this.Id = id; } // 淺表克隆方法 public abstract Prototype Clone(); public abstract Prototype SClone(); } /// <summary> /// 建立具體原型 /// </summary> public class ConcretePrototype : Prototype { public ConcretePrototype(string id) : base(id) { } /// <summary> /// 淺拷貝 /// </summary> /// <returns></returns> public override Prototype Clone() { // 調用MemberwiseClone方法實現的是淺拷貝 return this.MemberwiseClone() as Prototype; } /// <summary> /// 深拷貝 /// </summary> /// <returns></returns> public override Prototype SClone() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; return formatter.Deserialize(stream) as Prototype; } } //客戶端調用 class Client { static void Main(string[] args) { Prototype _prototype = new ConcretePrototype("id1"); //淺拷貝會在拷貝的多個對象間的引用類型改變都會改變,由於引用的是一個地址 Prototype clone1 = _prototype.Clone() as ConcretePrototype; Console.WriteLine("Cloned1:\t" + clone1.Id); //深克隆和單獨new一個對象的效果是同樣的 Prototype clone2 = _prototype.SClone() as ConcretePrototype; Console.WriteLine("Cloned2:\t" + clone2.Id); Console.ReadLine(); } }
五、建造者模式(彷佛有時也叫生成器模式,將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。)
典型應用相似ERP系統中的Bom表同樣,一個產品對象由不一樣的物料對象組成。如下是示例
/// <summary> /// 產品類 /// </summary> public class Product { // 產品組件集合 private IList<string> parts = new List<string>(); // 把單個組件添加到產品組件集合中 public void Add(string part) { parts.Add(part); } public void Show() { Console.WriteLine("產品開始在組裝......."); foreach (string part in parts) { Console.WriteLine("組件" + part + "已裝好"); } Console.WriteLine("產品組裝完成"); } } //建造者類 interface IBuilder { void BuildPartA(); void BuildPartB(); Product Product { get; } } //具體建造者實現類 public class Builder1 : IBuilder { Product product; public Builder1() { product = new Product(); } public void BuildPartA() { Product.Add("PartA"); } public void BuildPartB() { Product.Add("PartB"); } public Product GetProduct() { return product; } } //指揮調度者類 class Manufacturer { public void Construct(IBuilder builder) { builder.BuildPartA(); builder.BuildPartB(); } } // 客戶端調用 class Client { static void Main(string[] args) { // 實例化指揮者 Manufacturer newManufacturer = new Manufacturer(); // 準備建造者 IBuilder productBuilder = null; // 實例調用具體建造者執行任務 productBuilder = new Builder1(); newManufacturer.Construct(productBuilder); productBuilder.Product.show(); //....能夠實現其餘具體建造者... } }