敏捷软件开发 – OBSERVER模式

数字时钟

  我们有一个时钟对象。该对象捕获来自操作系统的毫秒终端(即时钟滴答),并把它们转换成时间。该队想知道如何从微秒数计算出秒数,如何从秒数计算出分钟数等等。它知道每个月有多少天,以及每年有几个月。它知道有关闰年的所有信息,并且可以判断出什么时候是闰年,而什么时候不是闰年。

  我们想创建一个数字时钟,可以把它摆放在桌面上,并且连续地显示时间。最简单的实现方式如下。

public void DisplayTime()
{
    while(true)
    {
        int sec = clock.Seconds;
        int min = clock.Minutes;
        int hour = clock.Hours;
        ShowTime(hour, min, sec);
    }
}

  显然,这不是最好的方法。为了重复地显示时间,它消耗了所有可用的CPU周期。其中,大部分的显示都是多余的,因为时间没有变化。也许,这个解决方案可以应用于数字手表或者数字挂钟中,因为在这些系统中,节省CPU周期不是非常重要的。

OBSERVER模式

  拉模型OBSERVER模式

  Clock被DigitalClock观察。DigitalClock通过ISubject接口注册到Clock中。无论任何原因,只要时间一改变,Clock就调用ISubjec的Notify方法。而ISubject的Notify方法会调用每个已注册的IObserver对象的Update方法。因此,每当时间发生变化时,DigitalClock都会接收到一个Update消息。

 

  OBSERVER模式是那种一旦你理解了,就会觉得导出都可以使用它的模式之一。这种间接关系非常好。你可以向各种对象注册观察者,而不用让这些对象显式的调用你。虽然这种间接关系是一种有用的管理依赖关系的方法,但是它很容易会被过分使用。过度的使用OBSERVER模式往往会导致系统难以理解和跟踪。

  推模型OBSERVER模式

  Notify方法和Update方法都带有一个参数。该参数是一个提示(hint)。它是通过Notify方法和Update方法从Employee传到SalaryObserver的。这个提示让SalaryObserver知道了雇员记录遭受了哪种变化。

  Notify和Update的EmployeeObserverHint参数可能是某种枚举、一个字符串或者一个包含了某个字段新、旧值的复杂数据结构。不管它是什么,他的值都被推到观察者中。

  要选择哪种OBSERVER模型完全取决于被观察对象的复杂性。如果被观察对象比较复杂,并且观察者需要一个提示,那么推模型是合适的。如果被观察对象比较简单,那么拉模型就很合适。

 

 

 

 

摘录自:[美]RobertC.Martin、MicahMartin著,邓辉、孙鸣译 敏捷软件开发原则、模式与实践(C#版修订版) [M]、人民邮电出版社,2013、351-367、

posted @ 2016-09-28 16:59  guqiangjs  阅读(304)  评论(0)    收藏  举报