注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 一个黑客与一个电脑白痴的..
 帮助

学习设计模式之旅 / 观察者模式 (Observers)


2008-07-08 08:52:05
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://maddish.blog.51cto.com/282288/86307
        观察者模式(Observers)  定义了对象之间的一对多依赖,这个一来,当一个对象改变状态时,它所有的依赖者都会收到通知并自动更新,主题和观察者定义了一对多的关系 观察者依赖于主题,只要主题状态一有改变,观察者就会接受到通知 根据通知的风格;
       当两个对象之间松耦合,它们依然可以交互,但不太清除彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题只知道观察者实现了某个接口(也就是Observer接口)主题不需要知道观察者的具体类是谁,做了些什么或其他的任何细节。任何时候我们可以添加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表。
      松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。所以我们为了交互对象之间的松耦合设计而在努力。
Demo - 气象监测应用系统
     气象观测局专利申请在WeatherData对象中,由WeatherData负责追踪天气状态。成功以后以供布告板显示,由可能很多不同的布告板,每个布告板的显示都有所不同,并且当Weather对象得到新的数据时,所有布告板都必须更新。
 
namespace Exercise.BureauOfMeteorologyBackup
{
    /// <summary>
    /// 主题的接口
    /// </summary>
    interface ISubject
    {
        /// <summary>
        ///  登记观测者
        /// </summary>
        /// <param name="o"></param>
        void RegisterObserver(IObserver o);

        /// <summary>
        ///  移除观察者
        /// </summary>
        /// <param name="o"></param>
        void RemoveObserver(IObserver o);

        /// <summary>
        ///  通知观察着
        /// </summary>
        /// <!--  
        ///     当主题状态改变时这个方法会被调用 以通知所有的观察者 -->
        void NotifyObservers();
    }

    class WeatherData : ISubject
    {

        /// <summary>
        /// <!-- 使用ArrayList的形式来记录观察者 -->
        /// </summary>
        private ArrayList observers;

        private float temperature;

        private float humidity;

        private float pressure;

        public WeatherData(){
            observers = new ArrayList();
        }

ISubject 成员#region ISubject 成员

        /// <summary>
        ///  当注册观察者时 只需要添加到ArrayList后面即可
        /// </summary>
        /// <param name="o"></param>
        public void RegisterObserver(IObserver o)
        {
            observers.Add(o);
        }

        /// <summary>
        /// 当取消注册的时只需要从ArrayList移除即可
        /// </summary>
        /// <param name="o"></param>
        public void RemoveObserver(IObserver o)
        {
            int i = observers.IndexOf(o);

            if (i >= 0){
                observers.Remove(i);
            }
        }

        /// <summary>
        /// 通知所有观察者新的状态  
        /// </summary>
        public void NotifyObservers()
        {
            for (int i = 0; i < observers.Count; i++){

                IObserver observer = (IObserver)observers[i];

                observer.Update(temperature, humidity, pressure);

            }
        }

        #endregion

        /// <summary>
        ///  当从气象局得到更新观测值时 通知所有观察者
        /// </summary>
        public void MeasurementsChanged(){
            NotifyObservers();
        }

        public void SetMeasurements(float temperature, float humidity, float pressure)
        {
            Console.WriteLine("Began to inform all observers ..");

            this.temperature = temperature;

            this.humidity = humidity;

            this.pressure = pressure;

            MeasurementsChanged();  

            Console.WriteLine("End to all observers ..");
        }
    }
}


namespace Exercise.BureauOfMeteorologyBackup
{
    /// <summary>
    /// <!-- 所有的气象局组件都实现此观察者接口 主题在需要通知观察者时 有一个共同的接口 -->
    /// </summary>
    interface IObserver
    {
        /// <summary>
        ///  <!-- 当气象局观测值改变时 主题会把这些状态值当作方法的参数 传递给观察者 -->
        /// </summary>
        void Update(float temperature, float humidity, float pressure);
    }

    interface IDisplayElement
    {
        /// <summary>
        ///  当布告板需要显示时 调用此方法
        /// </summary>
        void Display();
    }
}

namespace Exercise.BureauOfMeteorologyBackup.Display
{
    class CurrentConditions: IObserver ,IDisplayElement
    {
        private float temperature;

        private float humidity;

        private ISubject weatherData;

        public CurrentConditions(ISubject weatherData)
        {
            this.weatherData = weatherData;

            weatherData.RegisterObserver(this);
        }

IDisplayElement 成员#region IDisplayElement 成员

        /// <summary>
        ///  显示最近的温度和湿度
        /// </summary>
        public void Display()
        {
            Console.WriteLine(
                "Current conditions : " + temperature +
                    "  F degrees and " + humidity + "% humidity");
        }

        #endregion

IObserver 成员#region IObserver 成员

        /// <summary>
        ///  温度和湿度保存然后显示
        /// </summary>
        public void Update(float temperature, float humidity, float pressure)
        {
            this.temperature = temperature;

            this.humidity = humidity;

            Display();
        }

        #endregion
    }
}
namespace Exercise.BureauOfMeteorologyBackup.Display
{
    class Forecast:IObserver,IDisplayElement
    {
        private float temperature;

        private float humidity;

        private WeatherData weatherData;

        public Forecast(WeatherData weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }

IObserver 成员#region IObserver 成员

        public void Update(float temperature, float humidity, float pressure)
        {
            this.temperature = temperature;

            this.humidity = humidity;
            
            Display();
        }

        #endregion

IDisplayElement 成员#region IDisplayElement 成员

        public void Display()
        {
            Console.WriteLine(
                "Forecast : " + temperature +
                    "  F degrees and " + humidity + "% humidity");
        }

        #endregion
    }
}

本文出自 “maddish” 博客,请务必保留此出处http://maddish.blog.51cto.com/282288/86307


附件下载:
  1
  2




    文章评论
 
2008-07-09 10:52:39
恩 现在要学的就是设计模式 支持

 

发表评论

昵   称:
验证码:  点击图片可刷新验证码  博客过2级,无需填写验证码
内   容: