观察者模式

观察者模式 :定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的多有依赖这都会收到通知并自动更新。

   简单的说这种模式就像生活中的报社和订阅报纸的人一样  , 如果你订阅了报纸(登记为观察者),报社有有新报纸就会第一时间送给你。如果你退订(撤销观察者),报社将不在通知你

实现观察者模式的方法不止一种,但是以保管Subject和Observer接口的设计方式最常见。

下面以一个具体的气象站系统为例子 ,更好的说明这种模式如何使用 

       设计  1确定主题(会改变状态的) ,气象信息(weatherdata)比如 温度,湿度,压力,风速等等

        2设计主题接口  

  

 public interface subject   //主题接口
    {
        public void registerObserver(observer o);  //观察者作为变量,登记观察者
        public void removeObserver(observer o); // 删除观察者
        public void notifyObservers(observer o);//通知 观察者  ,当主题改变时这个方法会被调用通知观察者
    }

     3具体的主题类 

 public class weatherData:subject //具体的主题类实现主题接口
    {
        private ArrayList observers;//添加一个arraylist来记录观察者,在构造函数中实例化
        private float temprature;//添加主题对象需要更新数据的私有字段
        private float humidity;
        private float pressure;
        public weatherData()
        {
            observers = new ArrayList();
        }
        public void registerObserver(observer o) //注册观察者,只需要把它加入到arraylist中
        {
            observers.Add(o);
        }
        public void removeObserver(observer o)// 观察者取消注册时,从list中删除
        {
         //   observers.Remove(o);
            int i = observers.IndexOf(o);
            if (i>=0)
            {
                observers.RemoveAt(i);
            }
        }
        public void notifyObservers()//通知每一个观察者,主题对象的状态改变,需要更新数据
        {
            foreach (observer ob in observers)
            {
                ob.update(temprature, humidity, pressure);  //观察者实现了update方法来更细数据
            }
           
        }
        public void measurementsChanged() //当气象站得到更新的观察值,通知观察者
        {

            notifyObservers();
        }

        public void setMeasurements(float temprature, float humidity, float pressure)//模拟数据更新
        {
            this.temprature = temprature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChanged(); //调用更新通知方法
        }
        //其他方法
    }

      4 确定观察者(需要用到主题状态数据的对象)

                 5 观察者接口

public interface observer   //观察者接口
    {
        public void update(float temp,float humidity,float pressure);
    }

     在添加一个接口用来显示 数据

  public interface displayElement   //这个接口只有一个方法用来更新显示数据的
    {
        public void display();
    }

      

 6 具体观察者,只举一个例子

 public class CurrentConditionsDisplay:observer,displayElement
    {
        private float humidity; //根据需要选择主题提供的数据
        private float pressure;
        private subject weatherdata;  // 主题对象 ,在构构造函数中实例化 
        public CurrentConditionsDisplay(subject weatherdata)
        {
            this.weatherdata = weatherdata;//保存 主题 对象的引用 ,使得观察者以后可以撤销注册
            weatherdata.registerObserver(this);//登记自己
        }
        public void update(float temp, float humidity, float pressure)
        {
            this.humidity = humidity;  //把更新的数据保存到私有成员中
            this.pressure = pressure;
            display();  //  然后调用display()
       //通知时需要的其他方法
} public void display(){ } }

  测试  

         

 protected void Page_Load(object sender, EventArgs e)
        {
            weatherData weatherData = new weatherData();//首先建立一个主题对象
            CurrentConditionsDisplay ccd = new CurrentConditionsDisplay(weatherData);//建立一个观察者登记在主题对象上
            weatherData.setMeasurements(11, 22, 33);//模拟主题对象数据更新 ,然后ccd对象会自动收到通知做出相应动作
            
        }

 要点 :1观察者模式定义对象之间1对多的关系

       2主题用一个共同的接口更新观察者

     3主题不需要知道观察者的内部细节,只需要知道他实现可观察者接口

遵循的设计原则:  1封装变化,将固定不变和变化分离,在观察者模式中,会改变的是主题的状态,以及观察者的数目和类型。用这个模式你可以改变依赖于主题状态的对象,

      却不必改变主题。这就叫提前规划

                  2针对接口编程,而不是针对实现,主题与观察者都使用接口,观察者利用主题接口,向主题注册,而主题利用观察者接口通知观察者,这样可以让两者之间

      运作正常,又具有松耦合的特点。

                         3多用组合,少用继承(观察者和主题如何搭配的),观察者模式利用“组合”将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运

      行时利用组合的方式产生的。

    

             

       

原文地址:https://www.cnblogs.com/wangjian920110/p/5392614.html