zoukankan      html  css  js  c++  java
  • 设计模式(一)观察者模式

    观察者模式 定义了对象之间的一对多的依赖,这样一来,当一个对象状态改变时,他的

    多有依赖都会受到通知并自动更新。

    本例为一个温度基站,和三个终端。温度基站为广播类WeatherData,三个终端监听者类分别为:TVDispaly,FactoryDisplay,MobileDisplay

    其中,Observable为广播类父类,含有基本的方法。

    Observer类为监听者接口,监听者需实现updata方法。

    Display为显示接口,需实现display方法。

    ObserverDemo为测试类。

    下面直接上代码,注释很清晰。基本上很容易理解。

    Observable.java

    package observer;
    /*
     * @author trojan
     * 广播类的父类
     * 
     */
    public class Observable {
        protected boolean change = false;
        
        public void setChanged() {
            change = true;
        }
        
        public void notifyObservers(Object arg) {}
        public void notifyObservers(){ notifyObservers(null);}
        public void addObserver(Observer observer){}
    }

    WeatherData.java

    package observer;
    /*
     * @author trojan
     * 该类为广播类
     */
    import java.util.ArrayList;
    
    public class WeatherData extends Observable {
        //温度
        private float temperature;
        //湿度
        private float humidity;
        //污染指数
        private float pollution_index;
        ArrayList<Observer> observers = new ArrayList<Observer>();
        
        public WeatherData(){ }
        
        //增加监听者
        public void addObserver(Observer observer){
            observers.add(observer);
        }
        
        //将更改广播给所有监听者
        public void notifyObservers(Object arg) {
            if(change){
                for(Observer observer : observers){
                    observer.update(this,arg);
                }
            }
            change = false;
        }
        
        public void notifyObservers() { notifyObservers(null);}
        
        public void stateChange() {
            //调用notifyObservers之前应调用状态改变标志函数
            setChanged();
            notifyObservers();
        }
        
        //设置状态后,将调用stateChange函数,通知监听者
        public void setState(float temperature, float humidity, float pollution_index) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pollution_index = pollution_index;
            stateChange();
        }
        
        
        public float getTemperature() {
            return temperature;
        }
        public void setTemperature(float temperature) {
            this.temperature = temperature;
        }
        public float getHumidity() {
            return humidity;
        }
        public void setHumidity(float humidity) {
            this.humidity = humidity;
        }
        public float getPollution_index() {
            return pollution_index;
        }
        public void setPollution_index(float pollution_index) {
            this.pollution_index = pollution_index;
        }
        
        
    }

    Display.java

    package observer;
    /*
     * @author
     * 显示接口
     */
    public interface Display {
        public void display();
    }

    Observer.java

    package observer;
    /*
     * @author trojan
     * 这是一个监听者的接口,需要实现updata方法
     * 该方法可以被广播者调用,向监听者广播数据,或者说是一种推的方式
     * 监听者可以可以调用该方法主动更新数据,就像是一种拉的方式
     * 当然,对于每一个实现的监听者可能会有不同的数据需求
     * 所以,他们可以实现对自己感兴趣的那部分数据更新
     * 
     */
    public interface Observer {
        public void update(Object obj,Object arg);;
    }

    TVDisplay.java

    package observer;
    /*
     * @author trojan
     * 对于电视台来说可能需要的气象数据要比其他的设备多
     * 所以updata需要更新更多的数据
     */
    public class TVDisplay implements Observer, Display{
        Observable observable;
        private float temperature;
        private float humidity;
        private float pollution_index; 
        
        //变成一个监听者
        public void becomeOberser(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);;
        }
    
        @Override
        public void update(Object obj, Object arg) {
            if(obj instanceof WeatherData){
                WeatherData weatherData = (WeatherData)obj;
                this.temperature = weatherData.getTemperature();
                this.humidity = weatherData.getHumidity();
                this.pollution_index = weatherData.getPollution_index();
            }
            
        }
        
        @Override
        public void display() {
            System.out.println("WeatherData:
    "
                    + "temperature: "+temperature +"
    "
                    +"humidity"+humidity+"
    "
                    +"pollution_index:"+pollution_index);
                
        }
    
    
    }

    FactoryDisplay.java

    package observer;
    /*
     * @author torjan
     * 工厂显示平台所需要的广播数据
     * 
     */
    public class FactoryDisplay implements Observer, Display{
    
        Observable observable;
        private float temperature;
        private float pollution_index; 
        
        //变成一个监听者
        public void becomeOberser(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);;
        }
    
        @Override
        public void update(Object obj, Object arg) {
            if(obj instanceof WeatherData){
                WeatherData weatherData = (WeatherData)obj;
                this.temperature = weatherData.getTemperature();
                this.pollution_index = weatherData.getPollution_index();
            }
            
        }
    
        @Override
        public void display() {
            System.out.println("WeatherData:
    "
                    + "temperature: "+temperature +"
    "
                    +"pollution_index"+pollution_index);
            
            
        }
    
    }

    MobileDisplay.java

    package observer;
    /*
     * @author
     * 手机平台所需要的广播数据
     * 
     */
    public class MobileDisplay implements Observer, Display {
    
        Observable observable;
        private float temperature;
        private float humidity;
        
        //变成一个监听者
        public void becomeOberser(Observable observable) {
            this.observable = observable;
            observable.addObserver(this);;
        }
    
        @Override
        public void update(Object obj, Object arg) {
            if(obj instanceof WeatherData){
                WeatherData weatherData = (WeatherData)obj;
                this.temperature = weatherData.getTemperature();
                this.humidity = weatherData.getHumidity();
            }
            
        }
        
        @Override
        public void display() {
            System.out.println("WeatherData:
    "
                    + "temperature: "+temperature +"
    "
                    +"humidity"+humidity);
                
        }
    
    
    }

    测试类:

    ObserverDemo.java

    package observer;
    
    public class ObserverDemo {
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData();
            FactoryDisplay factoryDisplay = new FactoryDisplay();
            MobileDisplay mobileDisplay = new MobileDisplay();
            TVDisplay tvDisplay = new TVDisplay();
            
            weatherData.addObserver(factoryDisplay);
            weatherData.addObserver(mobileDisplay);;
            tvDisplay.becomeOberser(weatherData);
            
            weatherData.setState(23, 70, 120);
            
            factoryDisplay.display();
            mobileDisplay.display();
            tvDisplay.display();
        }
    }

    测试结果:

    WeatherData:
    temperature: 23.0
    pollution_index120.0
    WeatherData:
    temperature: 23.0
    humidity70.0
    WeatherData:
    temperature: 23.0
    humidity70.0
    pollution_index:120.0

    总结:

    设计原则:找出程序中会变化的方面,然后根据其和固定不变的方面相分离

    在观察者模式中,会改变的是主题的状态,以及观察者的数目和种类。用这个模式,可以改变依赖于主题状态的对象,却不必改变主题。

    设计原则:针对接口编程,不针对实现编程

    设计原则:多用组合,少用继承

  • 相关阅读:
    winform登录成功后打开主窗体的合理写法
    C#将字符串转换为整型的三种方法的总结
    win7下安装Oracle11g
    无法将文件“.exe”复制到“.exe”。文件“.exe”正由另一进程使用,因此该进程无法访问该文件
    GDI+
    “System.Data.SqlClient.SqlConnection”的类型初始值设定项引发异常
    winform中为ComboBox控件添加“请选择”或“全部”选项
    IE8不能上传、插入图片的解决办法!
    asp.net mvc实现上传文件
    winform关闭窗体时确认框提示两次
  • 原文地址:https://www.cnblogs.com/justenjoy/p/7021778.html
Copyright © 2011-2022 走看看