深入浅出设计模式-002:观察者模式(Observer Pattern)

来源:互联网 发布:mac搜狗输入法皮肤 编辑:程序博客网 时间:2024/05/17 05:15

深入浅出设计模式-002:观察者模式(Observer Pattern)

一:观察者模式 = 出版者(主题Subject)+订阅者(观察者Observer)
    定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。
    主题和观察者定义了一对多关系。观察者依赖此主题,只要主题状态一有变化,观察者就会被通知。

二:松耦合的威力:当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。
    设计原则:为了交互对象之间的松耦合设计而努力。

    Subject:这是主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。
    Observer:所有潜在的观察者必须实现观察者接口,这个接口只有UPDATE一个方法,当主题改变它时被调用。
    ConcreteSubject:实现主题接口,还用于在状态改变时更新所有当前观察者。
    ConcreteObserver:具体观察者可以是实现此接口的任意类。观察者必须注册具体主题,以便接口更新。

三:观察者定义了对象之间一对多的关系
    主题用一个共同的接口来更新观察者
    观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者的接口。
    使用此模式时,你可从被观察者出推或拉数据
    有多个观察者时,不可以依赖特定的通知次序
   
四:类似于,在网上公布电话,订阅者想订阅时,可以通过电话通知。
    public interface Observer{
        //当气象观测值改变时,主题会把这些状态值当做方法的参数,传递给观察者
        void update(float tmp, float humidity, float pressure);
    }
    public interface DisplayElement{
        //当布告需要显示时,调用此方法
        void display();
    }
    public class CurrentDistionsDisplay : Observer, DisplayElement{
        private float temperature;
        private float humidity;
        private Subject weatherData;
        public CurrentDistionsDisplay(Subject weatherData){
            //注册用
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }
        public void update(float tmp, float humidity, float pressure){
            temperature = tmp;
            this.humidity = humidity;
            display();
        }
        public void display(){
            Console.WriteLine("CurrentDistionsDisplay");
        }
    }
    public class StatisticsDisplay : Observer, DisplayElement{
        private float temperature;
        private float humidity;
        private Subject weatherData;
        public StatisticsDisplay(Subject weatherData){
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }
        public void update(float tmp, float humidity, float pressure){
            temperature = tmp;
            this.humidity = humidity;
            display();
        }
        public void display(){
            Console.WriteLine("StatisticsDisplay");
        }
    }
    public class ForecastDisplay : Observer, DisplayElement{
        private float temperature;
        private float humidity;
        private Subject weatherData;
        public ForecastDisplay(Subject weatherData){
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }
        public void update(float tmp, float humidity, float pressure){
            temperature = tmp;
            this.humidity = humidity;
            display();
        }
        public void display(){
            Console.WriteLine("ForecastDisplay");
        }
    }
    public interface Subject{
        //该观察者用来注册或被删除的
        void registerObserver(Observer o);
        void removeObserver(Observer o);
        //当主题状态改变时,这个方法会被调用,以通知所有的观察者
        void notifyObservers();
    }
    public class WeatherData : Subject{
        private ArrayList observers;
        private float temperature;
        private float humidity;
        private float pressure;
        public WeatherData(){
            observers = new ArrayList();
        }
        public void registerObserver(Observer o){
            observers.Add(o);
        }
        public void removeObserver(Observer o){
            int index = observers.IndexOf(o);
            if(index >= 0)
                observers.Remove(index);
        }
        public void notifyObservers(){
            for (int index = 0; index < observers.Count; index++){
                Observer observer = (Observer)observers[index];
                observer.update(temperature, humidity, pressure);
            }     
        }
        public void measurementsChanged(){
            notifyObservers();
        }
        public void setMeasurements(float temp, float humi, float press){
            temperature = temp;
            humidity = humi;
            pressure = press;
            measurementsChanged();
        }
    }

    static void Main(string[] args){
        WeatherData weatherData = new WeatherData();
        CurrentDistionsDisplay currentDisplay = new CurrentDistionsDisplay(weatherData);
        StatisticsDisplay statistics = new StatisticsDisplay(weatherData);
        ForecastDisplay forecast = new ForecastDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30);
        weatherData.setMeasurements(82, 70, 29);
    }

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 香港过境想去澳门怎么办 加拿大博士资格考试没通过怎么办 外国人没有学历怎么办工作签证 澳洲语言班挂了怎么办 英国学位翻译成文学硕士怎么办 没考上好的高中怎么办 毕业证12月发放申请英国怎么办 高二迷茫成绩差怎么办 高二期末考的差怎么办 法国留学签证办不下来怎么办 澳洲留学挂科签证续签怎么办 澳洲旅游签证被拒了怎么办 学校六级不让刷分怎么办 英国留学生怎么办申根签证 挂科太多拿不到学位证怎么办 ucl语言班没过怎么办 西澳大学工程挂科怎么办 澳洲语言班没过怎么办2018 杨浦区对口公立小学太差怎么办 公立小学太差了怎么办 澳大利亚出国留学怎么办-语言课程 学校不给释放信怎么办 重修费交不起钱怎么办 不想用家里的钱怎么办 三本学费太贵怎么办 从日本往中国汇款怎么办 学费钱大一没交怎么办 初中孩子和同学相处不好怎么办 使用假护照出国被发现怎么办 酒店忘记退房了怎么办 语言课申请不上怎么办 学会计的应届生想转行怎么办 上班熬不下去了怎么办 墨大选修挂科怎么办 日本签证年收入没有10w怎么办 做生意的办房贷没有薪资流水怎么办 澳洲医保卡丢了怎么办 澳洲爱他美上火怎么办 学信网学籍在籍没交学费怎么办 宝宝从床上摔下来怎么办 狗没打针被咬了怎么办