• 观察者模式



    在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

    情景设计

    设计一个应用,有三种布告板,分别显示目前的状况、气象统计及简单的预报。当WeatherObject对象会的最新数据时,三个布告板必须实时更新。而且这是一个可以扩展的气象站。可以让其他人开发自己的布告板。

    2.

    解决方案

    根据分析为有广告版能获取WeatherObject的数据,当数据变化时,就要更新数据,同时广告版有个模板制定规则。
    WeatherData对象知道如何跟物理气象站联系,以更新数据。WeatherData对象即时更新三个布告板的显示:目前状况(温度、温度、气压),气象统计和天气预报。
    我的思路是:在WeatherData中定义三个事件,当数据有更新时,就通过事件进行向这三个对象相应的数据。这样也可以很好完成任务,当时当新广告板,加入后,改动代码就很大了。先声明一个事件,然后再实现。
    这是一个发送接收的问题,同时当时接受方和发送发比较多的时候,管理起来就是比较大的问题,当发送发和接收方少的时候,另一方必须知道。针对面向对象的问题,使用超类编程思路,所以我们用观察者模式。

      3.

    观察者模式

    根据情景设计,先定义观察者模式:类图
    因为要知道观察者的状态,是否在线,所以要有注册和移除函数。
    观察者模式提供了一种对象设计,让主题者和观察者之间松耦合。因为主题只知道观察者实现了某一个接口。不知道观察者具体类是谁、做了什么。任何时候我们都可以增加新的观察者。因为主题唯一依赖的工时的Observer列表。当有新类型加入时,主题代码不需要修改,这样就实现了松耦合,视频组件中就用了这种方式。
    这里写图片描述
    上面设计中关键是在主题类中对观察者的接口进行操作,包括注册、以及接口功能的调用;在观察者类中国对主题接口进行操作,这样就将业务和对象区分开,松耦合目的达到了。
    其中关键的代码有:

    public class ConcreteSubject : ISubject
    {
        ArrayList observerList;
        public ConcreteSubject()
        {
            observerList = new ArrayList();
        }   
    
        public virtual void registObserver(Obsetver obj)
        {
        //注册观察者,对接口进行操作。
            observerList.Add(obj);
        }
    
        public virtual void removeObserver(Obsetver obj)
        {
            if (observerList.Contains(obj))
            {
                observerList.Remove(obj);
            }
        }
    
        public virtual void notifyObserver()
        {
           //向所有观察者发送数据,不关心观察者到底是多少
            foreach (Obsetver temp in observerList)
            {
                temp.Uadate();
            }
        }
    
    }
    View Code

    观察者代码

    public CurrentContion(ISubject weatherData)
        {
            //初始化时传入主题者实体类
            weatherData.registObserver(this);
        }
        public virtual void Uadate()
        {
            //主题者中进行调用了,这里数据添加
            throw new System.NotImplementedException();
        }
    
        public virtual void Dispaly()
        {
            throw new System.NotImplementedException();
        }
    View Code

    其中调用的函数为:

    public static void main(string [] args)
    {
        ConcreteSubject subject = new ConcreteSubject();
        CurrentContion observer = new CurrentContion(subject);
        subject.notifyObserver();
    }

    对于发布-订阅模型,大家都很容易能想到推模式与拉模式,用SQL Server做过数据库复制的朋友对这一点很清楚。在Observer模式中同样区分推模式和拉模式,我先简单的解释一下两者的区别:推模式是当有消息时,把消息信息以参数的形式传递(推)给所有观察者,而拉模式是当有消息时,通知消息的方法本身并不带任何的参数,是由观察者自己到主体对象那儿取回(拉)消息。
    .NET中的Observer模式
    在.NET中,相信大家对于事件和委托都已经不陌生了,这里就不具体多说了。利用事件和委托来实现Observer模式我认为更加的简单和优雅,也是一种更好的解决方案。因为在上面的示例中我们可以看到,虽然取消了直接耦合,但是又引入了不必要的约束(暂且这么说吧)。即那些子类必须都继承于主题父类,还有观察者接口等。效果及实现要点
    1.使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达到松耦合。
    2.目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。观察者自己决定是否需要订阅通知。目标对象对此一无所知。
    3.在C#中的Event。委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象,委托是比抽象Observer接口更为松耦合的设计。
    适用性
    1.当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
    2.当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
    3.当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
    总结
    通过Observer模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    .NET 3.5新特性(转)
    (转)常用正则表达式
    IEC 61850(转)
    好几年了,我又回来了。
    EPR和SAP的一些名词解释(转载)
    为blogs添加风采,添加奥运金牌榜及赛程
    VS2010崩溃重启解决方法.
    C#制作Windows service服务系列二:演示一个定期执行的windows服务及调试(windows service)(转载)
    C#中操作XML (修改完整版) (转)
    C#制作Windows service服务系列一:制作一个可安装、可启动、可停止、可卸载的Windows service
  • 原文地址:https://www.cnblogs.com/polly333/p/4705680.html
Copyright © 2020-2023  润新知