在一口一个设计模式--观察者模式中。我们已经知道怎样应用观察者模式,但通过近期的深入学习,发现观察者模式存在下面缺陷:
1.抽象通知者依赖于抽象观察者;
2.每一个详细观察者被调用的方法必须一致。
比方在机房收费系统中关于观察者模式的应用例如以下图所看到的:
这个设计存在下面问题:
1.抽象通知者须要把抽象观察者中的全部详细对象加入到集合中,以备向每一个详细观察者发送通知消息。
2.在发送通知消息时。详细观察者中被通知的方法必须一致,否则详细通知者无法完毕遍历;
3.更新卡内剩余金额、更新学生上机状态和保存学生上机记录这三个类没什么同样的地方。抽象出来的抽象观察者有点牵强。
经过苦苦的思索,我发现用C#中的托付和事件机制解决上述问题。代码结构例如以下:
抽象通知者:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public interface Informer { void Notify(); string Action { get; set; } } }详细通知者--正常下机:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public class Down : Informer { //声明一个托付 public delegate void EventHandler(); //为托付EventHandler加入事件Update public event EventHandler Update; public void Notify() { this.Update(); } private string action; public string Action { get { return action; } set { action = value; } } } }详细通知者--强制下机:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public class ForceDown : Informer { //声明一个托付 public delegate void EventHandler(); //为托付EventHandler加入事件Update public event EventHandler Update; public void Notify() { this.Update(); } private string action; public string Action { get { return action; } set { action = value; } } } }这个我们不须要抽象观察者,直接详细观察者--更新卡内剩余金额:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public class UpdateBalance { protected Informer dn; public UpdateBalance(Informer dn) { this.dn = dn; } public void ModifyBalance() { Console.WriteLine("{0}。该卡要下机,更新剩余金额!详细观察者--更新学生上机状态:", dn.Action); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public class OffLine { protected Informer dn; public OffLine(Informer dn) { this.dn = dn; } public void DelOnlineInfo() { Console.WriteLine("{0}!该卡要下机,删除正在上机表中的该卡信息!", dn.Action); } } }详细观察者--保存学生上机记录:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { public class SaveRec { protected Informer dn; public SaveRec(Informer dn) { this.dn = dn; } public void SaveLineRec() { Console.WriteLine("{0}!该卡要下机,保存上机记录信息!", dn.Action); } } }main方法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 观察者模式_托付 { class Program { static void Main(string[] args) { Down dn = new Down(); OffLine ol = new OffLine(dn); UpdateBalance up = new UpdateBalance(dn); SaveRec sr = new SaveRec(dn); dn.Update+=new Down.EventHandler(ol.DelOnlineInfo); dn.Update += new Down.EventHandler(up.ModifyBalance); dn.Update += new Down.EventHandler(sr.SaveLineRec); dn.Action = "刷卡下机"; dn.Notify(); } } }
程序运行结果例如以下所看到的:
通过运行结果,我们能够发现,在main方法中的正常下机事件dn.Update发生后,通过托付Down.EventHandler绑定到dn.Update事件上的三个方法ol.DelOnlineInfo、up.ModifyBalance、sr.SavelineRec都会被运行,达到观察者模式的效果。
如今我们能够发现:抽象通知者不再依赖于抽象观察者,由于抽象通知者通过托付通知详细观察者;详细观察者中被调用的方法也不是必需一致。由于仅仅需把想要运行的方法绑定到事件上即可。详细通知者也不必存在共性,不必牵强的对这三个类进行抽象。托付+事件完美解决上述问题。