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

简介:

写这篇文章主要想总结自己的工作经验,温故而知新。为什么叫做实用设计模式,所谓的实用模式就是说这些模式在本人的实际工作中使用过的,而且本人相对熟悉的,经验认为这些模式的使用能给系统带来有效改善。这些模式大部分来源于GoF,由于最近工作专注于移动的开发,因此会尽量使用移动开发的例子。

由于一直做监控程序的开发,对Observer模式的感受比较深,现在从一个例子入手,假如需求是实现一套手机告警监控系统,当一个智能手机接收到告警信息的时候需要通过不同的手段来通知用户,通知手段包括在LCD显示告警的图片和播放告警的声音。

clip_image002[3]

从上图可以看到这个系统主要分三个类,WarningManager负责管理和产生告警,AudioManager负责播放声音,DisplayManager负责显示告警图片。WarningManager和AudioManager以及DisplayManager是composition的关系,所谓composition就是强耦合,WarningManager包含了AudioManager和DisplayManager的引用,AudioManager和DisplayManager为WarningManager的成员。


复制代码
    public sealed class Warning
    {
        
public int Level{setget
;}
        
public int Type{setget
;}
    }

    
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那样,从消息源那里得到消息,然后进行处理。

clip_image004[4]

上图为Observer模式通用实现,消息源抽象成Subject类而消息处理类抽象成Observer类。由于C#在语法层built-in了Observer模式(使用delegate和event),所以,在实现上大大的简化了。上述例子使用Observer的实现如下。


复制代码
    public sealed class Warning
    {
        
public int Level{setget
;}
        
public int Type{setget
;}
    }

    
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);
            }
        }
    }
复制代码



clip_image006[4]

从上图看,WarningManager不再需要保存消息处理类的引用了,也就是说客户想增加新的通知手段,WarningManager不需要进行任何的修改。WarningManager 定义一个event提供给各个消息处理类进行订阅。消息处理类订阅该消息WarningManager.WarningEvent += HandleWarning;每当有告警产生的时候,WarningManager可以通知到各个订阅消息的消息处理类。哪怕某天客户想增加新需求,例如当收到告警的时候发送email,系统只要增加EmailManager处理类,WarningManager不需要任何的修改。

Observer模式应用广泛消息通知系统,我认为MS之所以把Observer直接built-in到C#语法里面,是因为Observer广泛的使用在界面(Winform和Webform)用户动作的处理上,在Forms上对每一个控件的用户动作事件处理都是注册事件到一个处理函数。

buttonSend.Click += new System.EventHandler(this.buttonSend_Click); 

这样Form就可以处理用户的异步动作。这也符合Hollywood Principle(Don't call us, we'll call you)。把form和具体的控件解耦,因为form的设计是相对固定的,但是控件可能不断增加。

反正只要有消息源和消息处理两大类的应用环境都可以考虑使用Observer模式,这模式为以后的扩展提供方便。我在之前的一个3G链接管理里面也使用了该模式,在一个智能手机里面,不同的应用可以共享一个3G的链接,当连接状态发生改变的时候,通过notify来通知已经注册的具体某个应用,到底有几个应用,3G链接管理程序完成不知道,3G链接管理模块对其他模块说,不要来call我,我不会告诉你详情,我在链接状态发生变化时会自动call了,你注册就完事了。原文见.NET Compact Framework 下的3G应用


    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/03/20/1417516.html,如需转载请自行联系原作者


相关文章
|
8天前
|
设计模式 SQL 算法
设计模式了解哪些,模版模式
设计模式了解哪些,模版模式
18 0
|
27天前
|
设计模式 Java uml
C++设计模式之 依赖注入模式探索
C++设计模式之 依赖注入模式探索
37 0
|
2月前
|
设计模式 前端开发 JavaScript
观察者模式 vs 发布-订阅模式:两种设计模式的对决!
欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚开始学习前端的读者们打造的。无论你是初学者还是有一些基础的开发者,我们都会在这里为你提供一个系统而又亲切的学习平台。我们以问答形式更新,为大家呈现精选的前端知识点和最佳实践。通过深入浅出的解释概念,并提供实际案例和练习,让你逐步建立起一个扎实的基础。无论是HTML、CSS、JavaScript还是最新的前端框架和工具,我们都将为你提供丰富的内容和实用技巧,帮助你更好地理解并运用前端开发中的各种技术。
|
4天前
|
设计模式 Java 数据库
小谈设计模式(2)—简单工厂模式
小谈设计模式(2)—简单工厂模式
|
9天前
|
设计模式 监控 Java
设计模式 - 观察者模式(Observer):Java中的战术与策略
【4月更文挑战第7天】观察者模式是构建可维护、可扩展系统的关键,它在Java中通过`Observable`和`Observer`实现对象间一对多的依赖关系,常用于事件处理、数据绑定和同步。该模式支持事件驱动架构、数据同步和实时系统,但需注意避免循环依赖、控制通知粒度,并关注性能和内存泄漏问题。通过明确角色、使用抽象和管理观察者注册,可最大化其效果。
|
4天前
|
设计模式 Java
小谈设计模式(9)—工厂方法模式
小谈设计模式(9)—工厂方法模式
|
1月前
|
设计模式 编译器
解析器模式--设计模式
解析器模式--设计模式
17 0
|
1月前
|
设计模式 算法
构建器模式--设计模式
构建器模式--设计模式
16 0
|
1月前
|
设计模式
【设计模式】中介模式
【设计模式】中介模式
|
2月前
|
设计模式 Java 关系型数据库
Java设计模式--创建模式工厂--用披萨订购案例 详细讲解三种工厂模式
Java设计模式--创建模式工厂--用披萨订购案例 详细讲解三种工厂模式
45 1