设计模式(二)观察者模式

今天回家做饭,时间就很紧张了,待会儿还要去洗澡,我有一个想法,就是买一个耳麦,这样在公司也能旁若无人的看书了,戴个耳机总是感觉不到那种隔离。

1.1 定义

观察者模式

在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖他的对象都会受到通知,并且自动更新。

OO原则

为交互对象之间的松耦合设计而努力。

ps

大量的GUI框架都使用了这个设计模式。

2.1 需求

  1. 有一个WeatherData对象,是一个气象站提供的气象数据对象。里面包括温度属性,压力属性等等
  2. 需要对外展示几种不同的布告板,包括温度类的,压力类的等等。
  3. WeatherData更新后,需要及时更新布告,同时,布告版可以随时增加和取消,也可能在现有基础上添加新的布告板。

2.2 分析

1.这个模式所体现出的设计原则就是为了交互对象的松耦合而努力,最主要耦合的地方,就是WeatherData和观察者Obererve之间的耦合。
2.解决办法就是用接口,就是面向抽象编程而不是面对实现编程,把Subject主题和Observer都抽象为接口,使用通用的方法来进行注册,更新等等一致的行为。
3.这也是动态类型的一种思想吧,像什么比是什么好用

3.1实现

首先是接口的构造:

  public interface IObserver
    {
        //主题为变量是方便观察者知道是哪个主题更新的他
        void update(ISubject sub, string temp, string pressure);
    }
    public interface IDisplayElement
    {
        void display();
    }
    public interface ISubject
    {
        void registerObserver(IObserver observer);
        void removeObserver(IObserver observer);
        void notifyObserver();
    }

显示功能和观察监视是两个功能,虽然在这个具体的业务场景里面他们是一同出现的,但是还是要用两个接口分别表示,不然无法复用,而且强耦合了。

然后就是Observer的具体类的实现:

 public class Temperature : IObserver, IDisplayElement
    {
        private string temp;
        private string pressure;
        private WeatherData weatherData;
        public Temperature(WeatherData w)
        {
            weatherData = w;
            weatherData.registerObserver(this);
        }
        public void display()
        {
            Console.WriteLine(" i am temperatureObserver,now temp is {0} and pressure is {1}", temp, pressure);
        }

        public void update(ISubject sub, string temp, string pressure)
        {
            this.temp = temp;
            this.pressure = pressure;
            display();
        }
    }

这里就放了一个,其他的结构基本一致。
然后就是最复杂的WeatherData,Subject的具体实现

   public class WeatherData : ISubject
    {
        private bool ischanged = false;
        private List<IObserver> ObserverList;
        private string temp;
        private string pressure;
        public WeatherData()
        {
            ObserverList = new List<IObserver>();
        }
        public void setMeasurement(string temp, string pressure)
        {
            this.temp = temp;
            this.pressure = pressure;
            this.changed();
        }
        private void setChanged()
        {
            ischanged = true;
        }
        public string getTemperature()
        {
            Random r = new Random();
            return r.Next(0, 100) + "℃";
        }
        public string getPressure()
        {
            Random r = new Random();
            return r.Next(0, 100) + "p";
        }
        public void changed()
        {
            setChanged();
            notifyObserver();
        }
        public void notifyObserver()
        {
            if (ischanged == true)
            {
                foreach (var item in ObserverList)
                {
                    item.update(this, this.temp, this.pressure);
                }
            }
            ischanged = false;
        }

        public void registerObserver(IObserver observer)
        {
            if (ObserverList.IndexOf(observer) < 0)
            {
                ObserverList.Add(observer);
            }
            else
            {
                Console.WriteLine("不可以重复注册");
            }
        }

        public void removeObserver(IObserver observer)
        {
            if (ObserverList.IndexOf(observer) >= 0)
            {
                ObserverList.Remove(observer);
            }
        }
    }

其中ischanged 属性是后加上去的,为了框架可以更加灵活,比如WeatherData更新非常频繁,而布告板不需要如此频繁和精度的更新,我们就可以在ischanged 属性上做文章,把不需要更新情况过滤掉就可以了。

在Java的内置支持的观察者模式中,数据的更新其实有两种,一种是push推,一种是pull拉,就是Oberver对象自己去按需get数据,而不是被动的等待推送,这也是一个思路。

原文地址:https://www.cnblogs.com/codersun/p/6965088.html