设计模式
在上一篇文章里我通过具体场景总结了“.net面向对象的设计原则”,其中也多次提到一些设计模式方面的技术,可想而知,设计模式在我们的开发过程中也是必不可少的。今天我们就来简单交流下设计模式。对于设计模式的介绍呢,网上流行这么一句话“想要搞好对象,必须要熟知套路”,所以百度中说设计模式简介时“设计模式一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结”一点也没错,在开发过程中通过渗入一些设计模式,我们的设计效果又会怎么样呢?话不多说,直接进入正题吧!
一、设计模式的分类
GOF一共总结了23套设计模式,大致可以分为以下三类:
- 创造型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活,该类型包括:单件模式、抽象工厂、建造者模式、工厂方法模式和原型模式等5种。
- 结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式,该类型包括:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式等7种。
- 行为型模式
这些设计模式特别关注对象之间的通信。分为职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法、访问者模式等11种。
二、设计模式解析
常用设计模式浅析:
1、单件模式
结构图 :
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性 :
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
示意性代码:
1 //单件模式示意性代码 2 public class Singleton 3 { 4 //创建私有对象,保证只有一个对象 5 private static Singleton _instance; 6 7 //保护类型的构造函数,子类化可扩展 8 protected Singleton() { } 9 10 //提供公共访问点 11 public static Singleton Instance() 12 { 13 14 // 使用 'Lazy initialization',为对象实例化 15 if (_instance == null) 16 { 17 _instance = new Singleton(); 18 } 19 20 return _instance; 21 } 22 }
Singleton
特点总结:实例对外唯一、子类可以扩展并且提供 一个公共的访问点访问。
实际应用:
1 /// <summary> 2 /// 投票选举 3 /// </summary> 4 public class LoadBalancer 5 { 6 //实例唯一 7 private static LoadBalancer instance; 8 //选举人 9 private ArrayList servers = new ArrayList(); 10 //随机数 11 private Random random = new Random(); 12 //用于异步 13 private static object syncLock = new object(); 14 //保护构造函数,创建时添加选举人 15 protected LoadBalancer() 16 { 17 servers.Add("ServerI"); 18 servers.Add("ServerII"); 19 servers.Add("ServerIII"); 20 servers.Add("ServerIV"); 21 servers.Add("ServerV"); 22 } 23 //公共访问点,初始化投票对象 24 public static LoadBalancer GetLoadBalancer() 25 { 26 if (instance == null) 27 { 28 lock (syncLock) 29 { 30 if (instance == null) 31 { 32 instance = new LoadBalancer(); 33 } 34 } 35 } 36 37 return instance; 38 } 39 public string Server 40 { 41 get 42 { 43 int r = random.Next(servers.Count); 44 return servers[r].ToString(); 45 } 46 } 47 }
LoadBalancer
1 public class SingletonMain 2 { 3 static void Main() 4 { 5 LoadBalancer b1 = LoadBalancer.GetLoadBalancer(); 6 LoadBalancer b2 = LoadBalancer.GetLoadBalancer(); 7 LoadBalancer b3 = LoadBalancer.GetLoadBalancer(); 8 LoadBalancer b4 = LoadBalancer.GetLoadBalancer(); 9 10 if (b1 == b2 && b2 == b3 && b3 == b4) 11 { 12 Console.WriteLine("Same instance\n"); 13 } 14 15 // Load balance 15 server requests 16 for (int i = 0; i < 15; i++) 17 { 18 Console.WriteLine(b1.Server); 19 } 20 21 Console.ReadKey(); 22 } 23 }
SingletonMain
2、抽象工厂
结构图:
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性 :
- 个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时
示意性代码:
1 public abstract class AbstractFactory 2 { 3 public abstract AbstractProductA CreateProductA(); 4 public abstract AbstractProductB CreateProductB(); 5 } 6 public abstract class AbstractProductA { } 7 public abstract class AbstractProductB 8 { 9 public abstract void Interact(AbstractProductA a); 10 } 11 public class ConcreteFactory1 : AbstractFactory 12 { 13 public override AbstractProductA CreateProductA() 14 { 15 return new ProductA1(); 16 } 17 public override AbstractProductB CreateProductB() 18 { 19 return new ProductB1(); 20 } 21 } 22 public class ConcreteFactory2 : AbstractFactory 23 { 24 public override AbstractProductA CreateProductA() 25 { 26 return new ProductA2(); 27 } 28 public override AbstractProductB CreateProductB() 29 { 30 return new ProductB2(); 31 } 32 } 33 public class ProductA1 : AbstractProductA { } 34 public class ProductA2 : AbstractProductA { } 35 public class ProductB1 : AbstractProductB 36 { 37 public override void Interact(AbstractProductA a) 38 { 39 Console.WriteLine(this.GetType().Name + " interacts with " + 40 a.GetType().Name); 41 } 42 } 43 public class ProductB2 : AbstractProductB 44 { 45 public override void Interact(AbstractProductA a) 46 { 47 Console.WriteLine(this.GetType().Name + " interacts with " + 48 a.GetType().Name); 49 } 50 }
AbstractFactory
1 public class Client 2 { 3 private AbstractProductA _abstractProductA; 4 private AbstractProductB _abstractProductB; 5 6 // Constructor 7 public Client(AbstractFactory factory) 8 { 9 _abstractProductB = factory.CreateProductB(); 10 _abstractProductA = factory.CreateProductA(); 11 } 12 13 public void Run() => _abstractProductB.Interact(_abstractProductA); 14 }
Client
1 class AbstractFactoryMain 2 { 3 public static void Main() 4 { 5 // Abstract factory #1 6 AbstractFactory factory1 = new ConcreteFactory1(); 7 Client c1 = new Client(factory1); 8 c1.Run(); 9 10 // Abstract factory #2 11 AbstractFactory factory2 = new ConcreteFactory2(); 12 Client c2 = new Client(factory2); 13 c2.Run(); 14 15 Console.ReadKey(); 16 } 17 }
AbstractFactoryMain
特点总结:抽象,多态,一系列相关关联。
3、代理模式
结构图:
意图:为其他对象提供一种代理以控制对这个对象的访问。
适用性 :
- 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy 模式。
示意性代码:
1 public abstract class Subject 2 { 3 public abstract void Request(); 4 } 5 6 public class RealSubject : Subject 7 { 8 public override void Request() 9 { 10 Console.WriteLine("Called RealSubject.Request()"); 11 } 12 } 13 14 public class Proxy : Subject 15 { 16 RealSubject realSubject; 17 18 public override void Request() 19 { 20 // Use 'lazy initialization' 21 if (realSubject == null) 22 { 23 realSubject = new RealSubject(); 24 } 25 26 realSubject.Request(); 27 } 28 }
Proxy
实际应用:
1 /// <summary> 2 /// Subject接口 3 /// </summary> 4 public interface IMath 5 { 6 //加法操作 7 double Add(double x, double y); 8 //减法操作 9 double Sub(double x, double y); 10 //乘法操作 11 double Mul(double x, double y); 12 //除法操作 13 double Div(double x, double y); 14 } 15 16 /// <summary> 17 /// 具体实现类 18 /// </summary> 19 public class Math : IMath 20 { 21 public double Add(double x, double y) 22 { 23 return x + y; 24 } 25 public double Sub(double x, double y) 26 { 27 return x - y; 28 } 29 public double Mul(double x, double y) 30 { 31 return x * y; 32 } 33 public double Div(double x, double y) 34 { 35 return x / y; 36 } 37 } 38 /// <summary> 39 /// 代理类 40 /// </summary> 41 public class MathProxy : IMath 42 { 43 Math math; 44 public MathProxy() { math = new Math(); } 45 46 public double Add(double x, double y) { return math.Add(x, y); } 47 public double Sub(double x, double y) { return math.Sub(x, y); } 48 public double Mul(double x, double y) { return math.Mul(x, y); } 49 public double Div(double x, double y) { return math.Div(x, y); } 50 }
MathProxy
3、观察者模式
结构图:
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
适用性 :
-
当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用
-
当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
-
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
示意性代码:
1 /// <summary> 2 /// 操作抽象类 3 /// </summary> 4 public abstract class Subject 5 { 6 //观察者数组 7 private ArrayList observers = new ArrayList(); 8 //添加观察者 9 public void Attach(Observer observer) => observers.Add(observer); 10 //删除观察者 11 public void Detach(Observer observer) => observers.Remove(observer); 12 //通知观察者们 13 public void Notify() 14 { 15 foreach (Observer o in observers) 16 { 17 o.Update(); 18 } 19 } 20 } 21 /// <summary> 22 /// 具体操作类 23 /// </summary> 24 public class ConcreteSubject : Subject 25 { 26 // Property 27 public string SubjectState { get; set; } 28 } 29 /// <summary> 30 /// 观察者类 31 /// </summary> 32 public abstract class Observer 33 { 34 //更新 35 public abstract void Update(); 36 } 37 38 /// <summary> 39 /// 具体的观察者 40 /// </summary> 41 public class ConcreteObserver : Observer 42 { 43 private string name; 44 private string observerState; 45 46 // Constructor 47 public ConcreteObserver(ConcreteSubject subject, string name) 48 { 49 this.Subject = subject; 50 this.name = name; 51 } 52 53 public override void Update() 54 { 55 observerState = Subject.SubjectState; 56 Console.WriteLine("Observer {0}'s new state is {1}", name, 57 observerState); 58 } 59 60 // Property 61 public ConcreteSubject Subject { get; set; } 62 }
Observer
实际应用:
1 /// <summary> 2 /// 拍卖类 3 /// </summary> 4 public abstract class Stock 5 { 6 protected string symbol; 7 protected double price; 8 private ArrayList investors = new ArrayList(); 9 10 public Stock(string symbol, double price) 11 { 12 this.symbol = symbol; 13 this.price = price; 14 } 15 16 public void Attach(Investor investor) 17 { 18 investors.Add(investor); 19 } 20 public void Detach(Investor investor) 21 { 22 investors.Remove(investor); 23 } 24 25 public void Notify() 26 { 27 foreach (Investor investor in investors) 28 { 29 investor.Update(this); 30 } 31 Console.WriteLine(""); 32 } 33 34 // Properties 35 public double Price 36 { 37 get 38 { 39 return price; 40 } 41 set 42 { 43 price = value; 44 Notify(); 45 } 46 } 47 48 public string Symbol 49 { 50 get 51 { 52 return symbol; 53 } 54 set 55 { 56 symbol = value; 57 } 58 } 59 } 60 /// <summary> 61 /// IBM拍卖 62 /// </summary> 63 public class IBM : Stock 64 { 65 public IBM(string symbol, double price) : base(symbol, price) 66 { 67 } 68 } 69 /// <summary> 70 /// 投资商接口 71 /// </summary> 72 interface IInvestor { void Update(Stock stock); } 73 /// <summary> 74 /// 投资商 75 /// </summary> 76 public class Investor : IInvestor 77 { 78 private string name; private Stock stock; 79 80 public Investor(string name) 81 { 82 this.name = name; 83 } 84 85 public void Update(Stock stock) 86 { 87 Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", name, 88 stock.Symbol, stock.Price); 89 } 90 91 public Stock Stock 92 { 93 get { return stock; } 94 set { stock = value; } 95 } 96 }
ObserverExample
特点总结:抽象,依赖,一个方面依赖于另一方面。
好了,今天就总结到这里了欢迎纠错,谢谢!!!