.NET类库中发现设计模式:观察者模式

来源:互联网 发布:华为5a手机壳 淘宝 编辑:程序博客网 时间:2024/06/06 03:20

观察者模式:

        The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically. (观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新)

 

Subject(被观察的对象接口) 

         规定ConcreteSubject的统一接口;

         每个Subject可以有多个Observer;

ConcreteSubject(具体被观察对象)

         维护对所有具体观察者的引用的列表;

         状态发生变化时会发送通知给所有注册的观察者。

Observer(观察者接口)

         规定ConcreteObserver的统一接口;

         定义了一个update()方法,在被观察对象状态改变时会被调用。

ConcreteObserver(具体观察者)

         维护一个对ConcreteSubject的引用;

         特定状态与ConcreteSubject同步;

         实现Observer接口,通过update()方法接收ConcreteSubject的通知。

 

.NET框架里的应用

        跟【策略模式】一样,观察者模式的应用也十分广泛,几乎所有需要实现一对多信息同步的地方都会看到它的身影,只是具体的表现形式可能稍有差异。这里我们再举一个在.NET里使用观察者模式的例子,其实非常简单,大家肯定都用过,那就是C#里的“委托/事件机制”,在C#的事件中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标(Subject)对象。其实委托是比抽象Observer接口更为松偶合的设计,因为委托只要求挂接的方法的声名部分必须符合委托声名的格式,而不需要象接口一样必须要求类去完全实现之。说到这里可能有些朋友(这篇文章的观察者)会有些疑问,接口在C#里就是interface,委托是delegate,他们两个怎么能扯到一起呢?解答这个疑问,我们要从设计模式的哲学来考虑问题,观察者模式之所以叫观察者模式,并不是因为内部使用了ISubject 、IObserver等类来实现了如前面图2的结构的代码,而是因为这个模式解决了如下问题:“观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新”,也就是说,所有解决这个问题的方法都可以称做观察者模式。而且接口的概念也绝对不局限于C#里的interface,接口只是一个契约,用来规范代码的行为,delegate也是一个接口,它规定了什么样的方法可以加载到event中,这也是一个契约,只是这个契约要比interface更简单。

       如果你曾经在ASP.NET和WinForm中写过程序,那么你可能已经使用过委托和事件,事件就是Subejct,而委托就是Observer,让我们来看看利用事件来实现的观察者模式的例子:

    public class Subject
    {
        public Subject() { }
        public EventHandler Event1;

        public void RaiseEvent1()
        {
            if (Event1 != null)
                Event1(null, null);
        }
    }

    public class Observer
    {
        public Observer(Subject s)
        {
            s.Event1 += new EventHandler(HandleMethod);
        }

        public void HandleMethod(object obj, EventArgs e)
        {
            Console.WriteLine("Observer is done");
        }
    }

        窗体按钮控件暴露了一个在按钮点击时能够通知Observer的点击事件,任何一个需要响应该事件的Observer仅仅只需要向这个事件注册一个委托(new EventHandler(HandleMethod) 便是一个委托,注册一个委托就是+=给Event1事件)。窗体按钮控件并不依赖于任何一个潜在的Observer,每一个Observer仅仅只需要知道这个事件的委托签名格式就OK了(在这个实例里委托就是EventHandler),因为EventHandler是一个委托类型而不是一个接口,所以每个Observer不需要去实现一个格外的接口,如果一个Observer已经有了一个符合委托签名格式的方法,那么它仅仅只需要把这个方法注册到Subject的事件中去。通过使用委托和事件,观察者模式能将Subject与Observer解耦(也就是Subject不需要显式的去调用Observer的某一个方法)!

 

应用场景和优缺点:

       上面已经对观察者模式做了比较详细的介绍,还是那句话,人无完人,模式也不是万能的,我们要用好设计模式来解决我们的实际问题,就必须熟知模式的应用场景和优缺点:

       观察者模式的应用场景:

       1、  对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。

       2、  对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。

       观察者模式的优点:

       1、  Subject和Observer之间是松偶合的,分别可以各自独立改变。

       2、  Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。

       3、  遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

       观察者模式的缺陷:

       1、  松偶合导致代码关系不明显,有时可能难以理解。(废话)

       2、  如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)

相关原则

       相信大家现在对观察者模式都应该很清楚了吧!OK!那么,就像我们在前面的文章里反复强调的一样,设计原则远比模式重要,学习设计模式的同时一定要注意体会设计原则的应用。这里我们再来看看观察者模式里都符合那些设计原则。

       1、  Identify the aspects of your application that vary and separate them from what stays the same. (找到系统中变化的部分,将变化的部分同其它稳定的部分隔开。)

       在观察者模式的应用场景里变化的部分是Subject的状态和Observer的数量。使用Observer模式可以很好地将这两部分隔离开,我们可以任意改变Observer的数量而不需要去修改Subject,而Subject的状态也可以任意改变,同样不会对其Observer有任何影响。

       2、  Program to an interface,not an implementation.(面向接口编程,而不要面向实现编程。)

       Subject和Observer都使用接口来实现。Subject只需要跟踪那些实现了IObserver接口的对象,所以其只依赖于IObserver;而所有Observer都通过ISubject接口来注册、撤销、接收通知,所以它们也只依赖于 ISubject;所以这是面向接口编程的,这样的实现方式使得Subject和Observer之间完全没有任何耦合。

       3、  Favor composition over inheritance.(优先使用对象组合,而非类继承)

        观察者模式使用对象组合将Subject和若干observer联系起来。它们之间的关系不是通过类的继承而是在运行时的动态组合。

参考:http://www.cnblogs.com/zhongkeruanjian/archive/2006/03/18/352766.html

http://www.cnblogs.com/justinw/archive/2007/05/02/734522.html

原创粉丝点击