一、概述

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。[GOF 《设计模式》]

看了Terrylee.NET设计模式(19):观察者模式(Observer Pattern,个人认为其模式的推导比较清晰,但感觉举的例子不是很好,和实际项目还是有些脱离。正好手上有一小项目应用了此模式,不知应用的是否正确,如果理解的不到位,请大家指正。此文算是对.NET设计模式(19):观察者模式(Observer Pattern的一个补充吧,不知Terrylee是否允许。

二、观察者模式结构图:

三、实际列子

一监控系统,需要根据系统某些变化报警,报警方式有Email、短信等多种,以后可能会变化。怎么演绎到观察者模式就不再多说了(如果需要的话再补充,一般参考Terrylee的文章即可明白)。
  

IAlarm是报警接口。当我们的系统需要添加报警方式的时候只需实现IAlarmWarn方法即可。Email类是Email报警的实现,SMS类是短信报警的实现。

MonitorContainer是监视器(抽象类)相当于观察者。只负责通知变化,当子类调用Notify方法它即会通知报警模块报警,如EmailSMS(短信)

NetMonitor是其中的具体的监控模块,继承于MonitorContainer。当发现系统网络有问题时会调用父类的Notify方法。

MonitorContainer里的AddAlarm这里就省略了(把报警模块对象加入到ArraryList中)

Notify方法就是foreach下报警模块对象集合。(可参考.NET设计模式(19):观察者模式(Observer Pattern文章里的代码)

NetMonitor的调用代码:

Pulbic class NetMonitor

{

    Public 
void Monitor()

    
{

        MonitorContaniner netMonitor 
= new NetMonitor();
        IAlarm mailAlarm 
= new EmailAlarm();
        netMonitor. AddAlarm (mailAlarm);
//增加Eamil报警模块
        IAlarm smsAlarm 
= new SMSAlarm();
        netMonitor. AddAlarm (smsAlarm);
//增加SMS报警模块
        base.Notify();
    }

}

 

个人感觉各个模块间藕合的还是比较厉害。怎么办?于是我加入了IOC。我使用的是CastleIOC容器。

MonitorContainer具体代码:

 /// <summary>
      
/// 监控模块容器
     
/// </summary>


     
public abstract class MontiorContainer

     
{
         private statci 
IWindsorContainer container = null;
         
private string _alarmMessage;

         
statci MontiorContainer ()
         
{
                 container 
= new WindsorContainer("Alarm.xml");//报警器的设置文件

             }

         }

         
public void Notify()

         
{

              
if (container != null)

              
{

                   IConfiguration[] configuration 
= container.Kernel.ConfigurationStore.GetComponents();                  

                   
foreach (IConfiguration item in configuration)//依次调用报警模块

                   
{

//framework 1.1                      
IAlarm alarm = container.Resolve(item.Attributes["id"].ToString()) as IAlarm ;
//framework2可以使用
//IAlarm alarm = container.Resolve<IAlarm >(item.Attributes["id"].ToString());
                       alarm.Warn(_alarmMessage);
                   }

              }

         }


//扩展:如果需要根据监控情况而采取不同的报警方式,对应的需要修改Instance

/*public void RemoveAlarm()
         {
         }
         public void AddAlarm(string alarmType)
         {
         }
*/

          
//报警内容
         
public string AlarmMessage

         
{

              
set{ _alarmMessage = value;}

         }


 

Alarm.xml(Castle的标准配置)

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <components>

        <component id="EmailAlarm" service="Alarm.IAlarm,IAlarm" type="Alarm.EMailAlarm,EMailAlarm"/>

        <component id="SMSIAlarm" service="Alarm.IAlarm,IAlarm" type="Alarm.SMSAlarm,SMSAlarm"/>

    </components>

</configuration>

 

现在NetMonitor的调用代码:

Pulbic class NetMonitor
{
    Public 
void Monitor()
    
{
       
base.Notify();

    }

}



怎么样,简单吧。把藕合度大大降低了。

四、总结

通过Observer模式结合IOC容器,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性。

扩展报警模块不需对现有系统代码修改即可增加,具体的监控模块都不需知道怎么调用报警模块。

posted on 2006-11-30 13:09  try  阅读(3324)  评论(13编辑  收藏  举报