1.单例模式
单例模式恐怕是很多开发人员最先接触到的模式之一,可以认为就是一个全局变量。它的初始化过程无非就是一开始就new 一个instance,或者惰性初始化等需要用到的时候new 一个instance。这里需要注意的是在多线程情况下new一个instance。通常加上lock 可以解决问题。这里我们利用C# 的系统函数 Interlocked.CompareExchange
internal class SingletonOne { private static SingletonOne _singleton; private SingletonOne() { } public static SingletonOne Instance { get { if (_singleton == null) { Interlocked.CompareExchange(ref _singleton, new SingletonOne(), null); } return _singleton; } } }
2.责任链模式
在一些情况下,对一个消息(含事件)的响应和处理需要很多对象来参与,这些对象对消息的处理有前后顺序,形成一个处理链条,但对象是否真正处理消息有赖于在它之前的对象的处理策略,前一个对象处理后,后一个对象则不需参与处理,这就是责任链模式。现实中有很多类似的场景,比如上访,上访一般是从最基层的信访部门接受信访开始进行处理,如果下一级信访部门无法处理,则交给上一级部门进行处理,这样一级一级的处理,知道最高信访部门。这样所有层级的信访部门就构成了一个责任链。
责任链模式在设计中的应用很多,比如Delphi中对系统对消息的处理,对异常的处理等。只是建立责任链的方式可能不同,有的是建立明确的处理责任链,如消息处理一般是根据控件的Parent来建立责任链条;有的则是暗含一种处理机制,比如Delphi的异常处理(C#也类似)总是从最内层到外,从被调用对象到调用对象这条链进行。
简单责任链模式示例:
public abstract class Chain_Successor { protected Chain_Successor successor; //保存后继责任者的引用 /// <summary> /// 处理需求 /// </summary> /// <param name="request">需要处理的类</param> public abstract void HandleReqest(Chain_Request request); /// <summary> /// 设置后继责任者 /// </summary> /// <param name="successor">后继责任者</param> public void SetChain_Successor(Chain_Successor successor) { this.successor = successor; } } public class Chain_ConcreateHandleA : Chain_Successor { public Chain_ConcreateHandleA() { } public override void HandleReqest(Chain_Request request) { //如果自己能处理则处理,否则传递给后继者 if(request.Request_Type==1) { System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters); } else { if(this.successor!=null) successor.HandleReqest(request); } } } public class Chain_ConcreateHandleB : Chain_Successor { public Chain_ConcreateHandleB() { } public override void HandleReqest(Chain_Request request) { //如果自己能处理则处理,否则传递给后继者 if(request.Request_Type==2) { System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters); } else { if(this.successor!=null) successor.HandleReqest(request); } } } public class Chain_ConcreateHandleC : Chain_Successor { public Chain_ConcreateHandleC() { } public override void HandleReqest(Chain_Request request) { //如果自己能处理则处理,否则传递给后继者 if(request.Request_Type==3) { System.Windows.Forms.MessageBox.Show(this.ToString()+":"+request.Request_Parameters); } else { if(this.successor!=null) successor.HandleReqest(request); } } } public class Chain_Request { //下面的两个参数可更加具体需要进行构造 private int _Request_type; private string _Request_parameters; public Chain_Request(int Request_type,string RequestParameters) { this._Request_type = Request_type; this._Request_parameters = RequestParameters; } public int Request_Type { get { return _Request_type; } set { _Request_type = value; } } public string Request_Parameters { get { return _Request_parameters; } set { _Request_parameters = value; } } } public class Chain_Client { public static void Test() { Chain_Successor firstHandler = new Chain_ConcreateHandleA(); Chain_Successor secondHandler = new Chain_ConcreateHandleB(); Chain_Successor ThirdHandler = new Chain_ConcreateHandleC(); firstHandler.SetChain_Successor(secondHandler); secondHandler.SetChain_Successor(ThirdHandler); firstHandler.HandleReqest(new Chain_Request(2,"hello,the world!")); } }
3.简单工厂模式
角色:用户,工厂,产品
目的是使得用户将产品的消费和生产分开.在编程中就是将类的创建和使用分开.从而达到责任分离,其实这也是所有创建模式的目的之一.做法是工厂类根据用户的要求(参数)来返回不同的类的实例.
工厂实现:采用参数化的静态方法为用户提供类实例的创建,如下所示:
public static ProductType FactoryMethod(参数)
{
根据参数返回需要类的实例.
}
简单工厂有几种情况:
1.产品只有一种,这种情况下方法没必要带参数.
2.产品有多种,且属于同类型产品,则可以加入抽象产品.加入抽象产品的一个潜在好处是可以让用户可以不关心具体的产品,在设计和实现上可以做到一定程度上的延后联编.
3.产品有多种,且类型各异,则可以考虑采用其它模式或者提供多个工厂方法来实现.但不鼓励采用后者来实现(做事要专业).
4.在实际应用中产品角色,工厂角色以及用户角色都可以根据实际情况合并.(模式变形)
简单工厂模式的理解:
1.如果产品创建的时候需要用户提供指导,则简单工厂模式不适合,如果要适用就会使得工厂方法的参数过于复杂,因此本模式只适合用户不关心产品构造逻辑,只关心使用的情况下(不关心构建,只关心使用).
2.大多数情况下用户还是必须知道产品的具体细节,没有减少对细节的依赖(特殊情况,有抽象产品的情况下,在某些应用中可以减少对具体产品的细节依赖).
3.采用静态方法实现类的创建,好处是可以减少工厂类本身的创建,但缺点是失去了工厂类进行继承扩展的优点.
4.简单工厂模式的好处是实现了责任分离,对用户来讲同时也隐藏了构建产品的细节,而且实现起来比较简单.
5.增加产品的时候,工厂类需要修改,也违背了面向对象的开放封闭原则.
6.只适合产品类比较少的情况,如果产品类太多,会使得静态工厂方法过于庞大.
但现在有一种比较简单的办法,就是采用反射或者泛型来规避静态方法过多而使得工厂类庞大的问题.
4.观察者模式
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。在现实生活中的可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用。
实现:比如热水器在烧水的过程中,当水温即将烧开时,会发出报警的声音,显示器上会出现温度监控
public interface IObserver { /// <summary> /// 更新自身状态 /// </summary> void Update(int temp); }
/// <summary> /// IObserverable接口 /// </summary> public interface IObservable { /// <summary> /// 注册IObserver /// </summary> /// <param name="obj"></param> void Register(IObserver obj); /// <summary> /// 取消IObserver的注册 /// </summary> /// <param name="obj"></param> void Unregister(IObserver obj); }
// <summary> /// 抽 象基类 /// </summary> public abstract class SubjectBase:IObservable { private List<IObserver> container = new List<IObserver>(); public void Register(IObserver obj) { container.Add(obj); } public void Unregister(IObserver obj) { container.Remove(obj); } /// <summary> /// 通知所有注册了的Observe /// </summary> protected virtual void Notify(int temp) { foreach (IObserver observer in container) { //调用Observer的Update()方法 observer.Update(temp); } } }
public class Heater:SubjectBase { private int temp;//水温 protected virtual void OnBioiled() { base.Notify(temp); } public void GetMonitoring() { for (int i = 0; i <= 99; i++) { temp = i + 1; if (temp > 95) { OnBioiled(); } } } }
public class Alarm:IObserver { public void Update(int temp) { if (temp == 100) { Console.WriteLine("水烧开了"+temp); } else { Console.WriteLine("开始报警,水快烧开了>> " + temp); } } }
public class Screen:IObserver { public void Update(int temp) { if (temp == 100) { Console.WriteLine("水烧开了" + temp); } else { Console.WriteLine("水快烧开了>> " + temp); } } }
/// <summary> /// C#设计模式-观察者模式 /// </summary> class Program { static void Main(string[] args) { Heater heater = new Heater(); heater.Register(new Screen()); heater.Register(new Alarm()); heater.GetMonitoring(); } }
-
在上面的例子中,热水器是Subject,报警器和显示器是Observer,报警器和显示器关心热水器中的水温。
优点:
观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。
观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
观察者模式支持广播通信。被观察者会向所有的注册过的观察者发出通知。
缺点:
如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
虽然观察者模式可以随时使观察者知道所观察的对象发送了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎样发生变化的。
如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象可以同时监听某一个主题对象,这个主题对象在发生状态变化时,会通知所有观察者对象,使它们能够自动更新自己,解决的是“当一个对象的改变需要同时改变多个其他对象”的问题。