IOC,观察者模式,项目的实际应用

一、概述

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

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

二、观察者模式结构图:
IOC,观察者模式,项目的实际应用

三、实际列子

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

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

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

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

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

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

NetMonitor的调用代码:

IOC,观察者模式,项目的实际应用Pulbic class NetMonitor
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用    Public 
void Monitor()
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用    
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用        MonitorContaniner netMonitor 
= new NetMonitor();
IOC,观察者模式,项目的实际应用        IAlarm mailAlarm 
= new EmailAlarm();
IOC,观察者模式,项目的实际应用        netMonitor. AddAlarm (mailAlarm);
//增加Eamil报警模块
IOC,观察者模式,项目的实际应用        IAlarm smsAlarm 
= new SMSAlarm();
IOC,观察者模式,项目的实际应用        netMonitor. AddAlarm (smsAlarm);
//增加SMS报警模块
IOC,观察者模式,项目的实际应用
        base.Notify();
IOC,观察者模式,项目的实际应用    }

IOC,观察者模式,项目的实际应用}

 

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

MonitorContainer具体代码:

IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用 /**//// <summary>
IOC,观察者模式,项目的实际应用      
/// 监控模块容器
IOC,观察者模式,项目的实际应用     
/// </summary>

IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用     
public abstract class MontiorContainer

IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用     
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用         private statci 
IWindsorContainer container = null;
IOC,观察者模式,项目的实际应用         
private string _alarmMessage;
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用         
statci MontiorContainer ()
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用         
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用                 container 
= new WindsorContainer("Alarm.xml");//报警器的设置文件

IOC,观察者模式,项目的实际应用             }

IOC,观察者模式,项目的实际应用         }

IOC,观察者模式,项目的实际应用         
public void Notify()
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用         
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用              
if (container != null)
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用              
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用                   IConfiguration[] configuration 
= container.Kernel.ConfigurationStore.GetComponents();                  
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用                   
foreach (IConfiguration item in configuration)//依次调用报警模块
IOC,观察者模式,项目的实际应用

IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用                   
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用
//framework 1.1                      
IOC,观察者模式,项目的实际应用
IAlarm alarm = container.Resolve(item.Attributes["id"].ToString()) as IAlarm ;
IOC,观察者模式,项目的实际应用
//framework2可以使用
IOC,观察者模式,项目的实际应用
//IAlarm alarm = container.Resolve<IAlarm >(item.Attributes["id"].ToString());
IOC,观察者模式,项目的实际应用                       alarm.Warn(_alarmMessage);
IOC,观察者模式,项目的实际应用                   }

IOC,观察者模式,项目的实际应用              }

IOC,观察者模式,项目的实际应用         }

IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用
//扩展:如果需要根据监控情况而采取不同的报警方式,对应的需要修改Instance
IOC,观察者模式,项目的实际应用

IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用
/**//*public void RemoveAlarm()
IOC,观察者模式,项目的实际应用         {
IOC,观察者模式,项目的实际应用         }
IOC,观察者模式,项目的实际应用         public void AddAlarm(string alarmType)
IOC,观察者模式,项目的实际应用         {
IOC,观察者模式,项目的实际应用         }
*/

IOC,观察者模式,项目的实际应用          
//报警内容
IOC,观察者模式,项目的实际应用         
public string AlarmMessage
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用         
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用              
setIOC,观察者模式,项目的实际应用{ _alarmMessage = value;}
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用         }


 

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的调用代码:

IOC,观察者模式,项目的实际应用Pulbic class NetMonitor
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用    Public 
void Monitor()
IOC,观察者模式,项目的实际应用IOC,观察者模式,项目的实际应用    
IOC,观察者模式,项目的实际应用{
IOC,观察者模式,项目的实际应用       
base.Notify();
IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用    }

IOC,观察者模式,项目的实际应用}

IOC,观察者模式,项目的实际应用
IOC,观察者模式,项目的实际应用


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

四、总结

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

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

转载于:https://www.cnblogs.com/try/archive/2006/11/30/577684.html