前面在学习C#时,留下一个疑问,为什么程序中会用到委托呢?到底有什么好处,使得我们有时候会选择“多此一举”呢?今天学习了设计模式中的观察者模式,让我领悟到了委托的一丝丝好处!
仍然以《大话设计模式》中提到的观察者模式的实例来说,那么观察者模式的类图可以表示为:
那么,我们仔细分析一下这个例子
1、看股票的观察者和看NBA的观察者都要依赖于抽象通知者给予他们的通知,他们才能及时更新工作状态。
2、而抽象通知者必须依赖抽象观察者才能实现通知的功能。
这其实就是观察者模式的核心:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,让他们能够自动更新自己。
最开始,我们使用观察者模式的目的是为了减少上图中的两个抽象子类之间的耦合(如前台类和看股票观察者类),即将两个系列的具有联系的子类分别抽象出一个抽象类,来减少类与类之间的耦合。
现在解决了,问题又来了。上图中,抽象通知者要依赖于抽象观察者,那么就意味着所有经通知者发出的消息,观察者必须进行更新,这样其实是不符合实际要求的。如果想要让不同的观察者具有不同的行为,只有观察者模式是不够的,这时就要用到——委托!
事件委托的实现:
class Program { static void Main(string[] args) { //实例化老板 Boss huhansan = new Boss(); //看股票的同事 StockObserver tongshi1 = new StockObserver("小王", huhansan); //看NBA的同事 NBAObserver tongshi2 = new NBAObserver("小李", huhansan); //将具体观察者所要执行的方法委托给“老板”的“更新”方法上了 huhansan .Update +=new EventHandler (tongshi1.CloseStockMarket ); huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding); //老板回来 huhansan.SubjectState = "老板我回来了!"; //发出通知 huhansan.Notify(); } } //通知者类,给具体观察者提供接口 interface Subject { void Notify(); string SubjectState { get; set; } } //声明一个委托(事件处理程序) delegate void EventHandler(); class Boss : Subject { //声明一事件Update,类型为委托EventHandler public event EventHandler Update; private string action; //老板状态 public void Notify() { Update(); } public string SubjectState { get { return action; } set { action = value; } } } //具体观察者类 ,看股票的同事 class StockObserver { //无参构造函数 private string name; private Subject sub; public StockObserver (string name,Subject sub) { this.name = name; this.sub = sub; } public void CloseStockMarket() { Console.WriteLine ("{0} {1}关闭股票行情,继续工作!",sub.SubjectState ,name); } } class NBAObserver { private string name; private Subject sub; public NBAObserver (string name,Subject sub) { this.name = name; this.sub = sub; } public void CloseNBADirectSeeding() { Console.WriteLine ("{0} {1}关闭NBA,继续工作!",sub.SubjectState ,name); } }
通过上述委托的使用,我们就可以减少原来观察者模式中抽象通知者对抽象观察者的依赖了。这就是委托的好处
它可以减少类之间的依赖,而且使得委托对象所搭载的方法并不属于同一个类(例子中委托对象为看股票的观察者类和看NBA的观察者类)。
当然,在使用委托时,也是有一定的要求的,那就是,委托的对象方法必须具有相同的原型和形式,也就是拥有相同的参数列表和返回值类型(例子中的两个子类对象都具有相同的形式)。
这样,通过与观察者模式结合,就可以看出在C#中使用委托的好处了!