我的实用设计模式之Observer模式

张开发
2026/4/16 10:52:56 15 分钟阅读

分享文章

我的实用设计模式之Observer模式
于一直做监控程序的开发对Observer模式的感受比较深现在从一个例子入手假如需求是实现一套手机告警监控系统当一个智能手机接收到告警信息的时候需要通过不同的手段来通知用户通知手段包括在LCD显示告警的图片和播放告警的声音。从上图可以看到这个系统主要分三个类WarningManager负责管理和产生告警AudioManager负责播放声音DisplayManager负责显示告警图片。WarningManager和AudioManager以及DisplayManager是composition的关系所谓composition就是强耦合WarningManager包含了AudioManager和DisplayManager的引用AudioManager和DisplayManager为WarningManager的成员。public sealed class Warning{public int Level{set; get;}public int Type{set; get;}}public class AudioManager{public void HandleWarning(Warning warning){Console.WriteLine(Play warning audio.);}}public class DisplayManager{public void HandleWarning(Warning warning){Console.WriteLine(Show warning picture.);}}public class WarningManager{private AudioManager audioManager new AudioManager();private DisplayManager displayManager new DisplayManager();private void HandleWarning(Warning warning){audioManager.HandleWarning(warning);displayManager.HandleWarning(warning);}}但是有一天客户想出一个新需求告警不仅仅需要发声和显示而且需要发短信。为了处理这个需求实现一个新的类SMSManager来处理短信操作。但是我们发现问题出现了WarningManager的功能对于这个新需求本来不需要任何的修改因为告警的管理和生产过程没有任何改变但是为了发送短信不得不把SMSManager的引用作为新的properties。也就是说每次这样类似需求的修改WarningManager都要做出相应的修改如下代码。public class SMSManager{public void HandleWarning(Warning warning){Console.WriteLine(Send out SMS.);}}public class WarningManager{private AudioManager audioManager new AudioManager();private DisplayManager displayManager new DisplayManager();private SMSManager smsManager new SMSManager();private void HandleWarning(Warning warning){audioManager.HandleWarning(warning);displayManager.HandleWarning(warning);smsManager.HandleWarning(warning);}}软件设计和开发人员在设计阶段需要把当前需求以及将来的变化的需求考虑清楚设计出可扩展性的系统根据Open-Closed Principle 应该把不变的需求WarningManager封装起来。同时适应变化的需求不同的通知方式。这样就引入了Observer模式来解决这一类问题。Observer模式可以广泛应用于消息通知系统消息通知系统主要有两部分组成一部分是消息源另外一部分为消息处理类。消息源就如WarningManager负责管理和产生消息。消息处理类就像AudioManager和DisplayManager那样从消息源那里得到消息然后进行处理。上图为Observer模式通用实现消息源抽象成Subject类而消息处理类抽象成Observer类。由于C#在语法层built-in了Observer模式使用delegate和event所以在实现上大大的简化了。上述例子使用Observer的实现如下。public sealed class Warning{public int Level{set; get;}public int Type{set; get;}}public class AudioManager{public AudioManager(){WarningManager.WarningEvent HandleWarning;}public void HandleWarning(Warning warning){Console.WriteLine(Play warning audio.);}}public class DisplayManager{public DisplayManager(){WarningManager.WarningEvent HandleWarning;}public void HandleWarning(Warning warning){Console.WriteLine(Show warning picture.);}}public class SMSManager{public SMSManager(){WarningManager.WarningEvent HandleWarning;}public void HandleWarning(Warning warning){Console.WriteLine(Send out SMS.);}}public sealed class WarningManager{public delegate void WarningEventHandler(Warning warning);public static event WarningEventHandler WarningEvent;private void Notify(Warning warning){WarningEventHandler warningEvent WarningEvent;if (warningEvent ! null){warningEvent(warning);}}}从上图看WarningManager不再需要保存消息处理类的引用了也就是说客户想增加新的通知手段WarningManager不需要进行任何的修改。WarningManager 定义一个event提供给各个消息处理类进行订阅。消息处理类订阅该消息WarningManager.WarningEvent HandleWarning;每当有告警产生的时候WarningManager可以通知到各个订阅消息的消息处理类。哪怕某天客户想增加新需求例如当收到告警的时候发送email系统只要增加EmailManager处理类WarningManager不需要任何的修改。Observer模式应用广泛消息通知系统我认为MS之所以把Observer直接built-in到C#语法里面是因为Observer广泛的使用在界面(Winform和Webform)用户动作的处理上在Forms上对每一个控件的用户动作事件处理都是注册事件到一个处理函数。

更多文章