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


    一、概述

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。[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容器,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性。

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

  • 相关阅读:
    合同主体列表添加两条合同主体,返回合并支付页面,支付总弹"请选择合同主体",删除后,竟然还能支付(改合并支付页面的字段状态)
    (TODO:)下载图片,报错:warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.
    GCD死锁 多线程
    iOS知识总结
    快速排序,冒泡排序,选择排序
    fight
    3D Touch
    Xcode 调试技巧
    右滑退出手势及隐藏导航栏存在的风险
    C语言-第5课
  • 原文地址:https://www.cnblogs.com/try/p/577684.html
Copyright © 2020-2023  润新知