• 观察者模式


    最近看了<Head First设计模式>里的观察者模式,代码逻辑并没有什么太花哨的东西,但是对于代码结构设计可扩展性有一定的启发.下面是书中内容的简单整理:

    业务需求:

    设计一个气象监测应用,在温度,气压,湿度变化时在公告板显示数据;

    需求分析:
    目的用于数据显示,所以可以将代码分为三块:监控设备,气象站数据,公告板
    业务流程:监控设备获取原始信息->气象站获取原始信息->通知公告板信息变更显示

    核心业务逻辑:

    气象站代码实现:
    public class WeatherData {
      // 更新公告板数据
      public void measurementsChanged() {
        // 获取最新温度,气压,湿度数据
        float temp = getTemperature();
        float humidity = getHumidity();
        float pressure = getPressure();
    
        // 更新公告板信息
        currentConditionsDisplay.update(temp,humidity,pressure);
      }
    }

    其实实现功能就是当监控设备的数据变化时,调取公告板更新显示数据;

    但是这个代码有一些问题:
      针对具体实现编程,未针对接口编程,代码耦合性高,可扩展性较差;

    所以这里可以用观察者模式进行规范,降低耦合性,增加扩展性;
    观察者模式:定义对象间一对多依赖,当一个对象状态变化时,它的所有依赖着都会收到通知并自动更新;
    类似于消息订阅,观察者统一在主题处注册,当有新消息时主题通知观察者,完成数据触发操作;
    消息获取存在推,拉两种消息获取方式:
      推:消息获取直接,但是信息量大,扩展时就要修改接口;
      拉:消息获取较复杂,但是扩展方便;

    观察者模式设计:

    定义三个接口:Subject(主题),Observer(观察者),DisplayElement(显示元素);

    定义具体实现类:WeatherData(气象数据)实现Subject接口;公告板实现Observer,DisplayElement接口;

    代码实现:

    主题接口:

    // 管理接收信息的观察者,进行消息通知
    public interface Subject {
      void registerObserver(Observer observer);
      void removeObserver(Observer observer);
      // 激活观察者状态更新
      void notifyObservers();
    }

    观察者接口:

    // 观察者,进行消息更新
    public interface Observer {
      /**
      * @Description: 更新观察者数据
      * @param subject:主题
      * @param obj:推送消息
      */
      void update(Subject subject,Object obj);
    }

    数据显示接口:

    public interface DisplayElement {
    	void display();
    }

    主题具体实现类:

    public class WeatherData implements Subject {
    	private List<Observer> observers;
    	private float temp;
    	private float humidity;
    	private float pressure;
    	private boolean changed;// 更新标识
    
    	public WeatherData() {
    		// 实例初始化再创建对象,缩短生命周期,减少资源占用
    		observers = new ArrayList<>();
    	}
    
    	@Override
    	public void registerObserver(Observer observer) {
    		observers.add(observer);
    	}
    
    	@Override
    	public void removeObserver(Observer observer) {
    		observers.remove(observer);
    	}
    
    	public void notifyObservers(Object org) {
    		if (changed) {
    			for (Observer observer : observers) {
    				observer.update(this, org);
    			}
    			changed = false;
    		}
    	}
    
    	@Override
    	public void notifyObservers() {
    		notifyObservers(null);
    	}
    
    	// 自身的更新方法
    	public void measurementsChanged() {
    		setChanged();
    		notifyObservers();
    	}
    
    	public void setMeasurements(float temp, float humidity, float pressure) {
    		this.temp = temp;
    		this.humidity = humidity;
    		this.pressure = pressure;
    		measurementsChanged();
    	}
    
    	// 设置更新标识,控制更新频率和状态
    	private void setChanged() {
    		changed = true;
    	}
    
    	public float getTemp() {
    		return temp;
    	}
    
    	public float getHumidity() {
    		return humidity;
    	}
    
    	public float getPressure() {
    		return pressure;
    	}
    	
    }

    公告板具体实现类:

    public class CurrentConditionDisplay implements Observer,DisplayElement{
    	private float temp;
    	private float humidity;
    	private Subject subject;
    
    	// 接收主题的消息激活
    	public CurrentConditionDisplay(Subject subject) {
    		this.subject=subject;
    		subject.registerObserver(this);
    	}
    
    	/**
    	 * @Description: 更新信息
    	 * @param subject:消息源主题
    	 * @param obj:接收参数
    	 */
    	@Override
    	public void update(Subject subject,Object obj) {
    		if(subject instanceof WeatherData) {
    			WeatherData WeatherData = (WeatherData)subject;
    			this.temp=WeatherData.getTemp();
    			this.humidity=WeatherData.getHumidity();
    			display();
    		}
    	}
    	@Override
    	public void display() {
    		System.out.println("Current conditions: "+temp+" F degrees and "+humidity+"% humidity");
    	}
    
    	public void cancelRegister() {
    		subject.removeObserver(this);
    	}
    }

    因为公共接口的抽取,让整体的代码层次更清晰,简单;降低了代码间的耦合度,这也让未来代码扩展更方便;

  • 相关阅读:
    WebMatrix简介与预览
    使用NuGet增加常见包引用
    用Jquery实现的一个Table的帮助js
    使用AspNetPager进行存储过程分页
    Android之旅AppWidget
    SQL积累
    【问题记录】Asp.net WebApplication和WebSite中用户控件的使用区别
    ActionScript 3.0工厂模式实例
    ActionScript 3.0 实现单态模式
    装饰器模式小结
  • 原文地址:https://www.cnblogs.com/chengmuyu/p/8855446.html
Copyright © 2020-2023  润新知