本文中尽可能在一页中可以简单明了的说明各类经常使用建立类型的设计模式,尽可能写的通俗易懂些(部分参照了其余地方的经典示例),其余类型设计模式将继续更新奉上。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(); //....能够实现其余具体建造者... } }