• [置顶] head first 设计模式之----Observer pattern


    浅谈设计模式之----观察者模式
         观察者模式也是我们日常程序编写中碰到比较多的一种设计模式。首先,所谓观察者模式定义就是指:在对象之间定义了一对多的依赖,这样一来,当一个对象的状态发生变化的时候,依赖它的多个对象都会收到通知并且自动更新。
         平时的运用中,我们一般用到Observer pattern的实现方式主要是:自定义主题(Subject)和Observer(观察者)和JDK自己封装的java.util.Observer和java.util.Observable(类似subject)来实现的。在这里,我主要讲述自定义的Observer pattern的实现吧。
         以下以气象预报站(WeatherStation)进行天气的预报为例子。气象站的需求是建立三块公布版,一块是当前气象预报(CurrentConditionDisplay)公布版、静态预报(StatisticDisplay)公布版、预报(ForeCastDisplay)公布版。其中主题的实现是气象站的数据提供(WeatherData)实现Subject(主题),观察者为Observer和DisplayElement两个接口。其中观察者的实现有三个,分别对应三块公布版。CurrentConditionDisplay、StatisticDisplay、ForestCastDisplay,散者均需要实现Observer和DisplayElement三个接口。从而,主题的实现类WeatherData通过调用观察者的接口通知观察者及时更新,观察者通过主题接口来向主题注册,在设计的过程中,会变的只是主题的状态和观察者的数目和类型。此模式可以改变依赖主题状态的对象而不该变主题的状态。
      以下是代码的实现
    package com.clark.observerpattern.subject;

    import com.clark.observerpattern.observer.Observer;

    /**
     * 气象站主题,其对应着多个Observer对象
     * @author Administrator
     *
     */
    public interface Subject {
        //注册一个Observer
        public void registerObserver(Observer obj);
        //remove一个Observer
        public void removeObserver(Observer obj);
        //当主题对象发生改变的时候,通知所有的Observer
        public void notifyAllObserver();
    }

    package com.clark.observerpattern.observer;
    /**
     * defination much observer object
     * @author Administrator
     *
     */
    public interface Observer {
        //defined a update method,parameter include temp,humidity,pressure
        public void update(float temp,float humidity,float pressure);
    }
    package com.clark.observerpattern.observer;
    /**
     * display 布告板的信息
     * @author Administrator
     *
     */
    public interface DisplayElement {
        void display();
    }

    package com.clark.observerpattern;

    import com.clark.observerpattern.observer.DisplayElement;
    import com.clark.observerpattern.observer.Observer;
    import com.clark.observerpattern.subject.Subject;

    class CurrentConditionsDisplay implements Observer, DisplayElement {
        private float temp;
        private float humidity;
        private Subject weatherData;
        @Override
        public void display() {
            System.out.println("current conditions:"+temp+" F degrees and "+humidity+"% humidity");
        }

        @Override
        public void update(float temp, float humidity, float pressure) {
            this.temp=temp;
            this.humidity=humidity;
            display();
        }
        public CurrentConditionsDisplay(Subject weatherData){
            this.weatherData=weatherData;
            //注册改Observer,从而在后面移除的时候方便关联
            weatherData.registerObserver(this);
        }
    }
    package com.clark.observerpattern.observer;
    import java.util.*;

    import com.clark.observerpattern.subject.Subject;
    import com.clark.observerpattern.subject.WeatherData;
    /**
     * 统计布告板
     * @author Administrator
     *
     */
    public class StatisticsDisplay implements Observer, DisplayElement {
        private float maxTemp = 0.0f;
        private float minTemp = 200;
        private float tempSum= 0.0f;
        private int numReadings;
        private Subject weatherData;

        public StatisticsDisplay(WeatherData weatherData) {
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }

        public void update(float temp, float humidity, float pressure) {
            tempSum += temp;
            numReadings++;

            if (temp > maxTemp) {
                maxTemp = temp;
            }
     
            if (temp < minTemp) {
                minTemp = temp;
            }

            display();
        }

        public void display() {
            System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
                + "/" + maxTemp + "/" + minTemp);
        }
    }

    package com.clark.observerpattern.observer;

    import com.clark.observerpattern.subject.Subject;
    import com.clark.observerpattern.subject.WeatherData;

    /**
     * 天气预报布告板的现场预报板块
     * @author Administrator
     *
     */
    public class ForecastDisplay implements DisplayElement, Observer {
        private float currentPressure = 29.92f;  
        private float lastPressure;
        private Subject weatherData;
        
        public ForecastDisplay(WeatherData weatherData) {
            this.weatherData = weatherData;
            weatherData.registerObserver(this);
        }

        public void update(float temp, float humidity, float pressure) {
            lastPressure = currentPressure;
            currentPressure = pressure;
            display();
        }

        public void display() {
            System.out.print("Forecast: ");
            if (currentPressure > lastPressure) {
                System.out.println("Improving weather on the way!");
            } else if (currentPressure == lastPressure) {
                System.out.println("More of the same");
            } else if (currentPressure < lastPressure) {
                System.out.println("Watch out for cooler, rainy weather");
            }
        }

    }
    package com.clark.observerpattern.subject;

    import java.util.ArrayList;

    import com.clark.observerpattern.observer.Observer;

    /**
     * 模拟气象站的具体主题Subject
     * @author Administrator
     *
     */
    public class WeatherData implements Subject {
        private ArrayList observers;
        private float temp;
        private float humidity;
        private float pressure;
        public WeatherData() {
            observers=new ArrayList();
        }
        @Override
        public void registerObserver(Observer obj) {
            observers.add(obj);
        }

        @Override
        public void removeObserver(Observer obj) {
            int i=observers.indexOf(obj);
            if(i>=0){
                observers.remove(i);
            }
        }

        @Override
        public void notifyAllObserver() {
            for (int i = 0; i < observers.size(); i++) {
                Observer o=(Observer) observers.get(i);
                o.update(temp, humidity, pressure);
            }
        }
        //当从气象站获取更新数据的时候,我们通知观察着
        public void measurementsChange(){
            notifyAllObserver();
        }
        //读取气象站数据
        public void setMeasurements(float temp,float humidity,float pressure){
            this.temp=temp;
            this.humidity=humidity;
            this.pressure=pressure;
            measurementsChange();
        }
    }


    package com.clark.observerpattern;

    import com.clark.observerpattern.observer.ForecastDisplay;
    import com.clark.observerpattern.observer.StatisticsDisplay;
    import com.clark.observerpattern.subject.WeatherData;

    /**
     * 气象站
     * @author Administrator
     *
     */
    public class WeatherStation {
        public static void main(String[] args) {
            WeatherData weatherData=new WeatherData();
            //先往Subject中添加所有注册的主题
            CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);
            StatisticsDisplay statistic=new StatisticsDisplay(weatherData);
            ForecastDisplay foreCast=new ForecastDisplay(weatherData);
            //再调用方法从主题中获取数据,从而在布告板中及时显示
            weatherData.setMeasurements(50, 80, 66);
            weatherData.setMeasurements(48, 80, 67);
            weatherData.setMeasurements(52, 80, 65);
        }
    }








      


  • 相关阅读:
    Linux C Socket编程原理及简单实例
    clock_gettime 用法
    Linux未来监控tracing框架——eBPF
    eBPF监控工具bcc系列五工具funccount
    【转】如何测量电源纹波?
    【转】在网页中运行VB6程序
    如何为互阻抗放大器电路选择具有足够带宽的运算放大器
    互阻放大器的稳定工作及其评估
    【原创】OPA857 TEST模式使用
    [转]What you need to know about transimpedance amplifiers – part 1
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3177855.html
Copyright © 2020-2023  润新知