大三学习软件工程这门课,状态一直很懵,原因是其中所谓的设计模式、设计方法都是前人们一步步总结出来的,我既没有功力深厚的编程底子,也没有任何工程项目的经验,一介学生,学好不易。
以下博文部分摘自Q-WHai的博客点击打开链接
下面总结一下设计模式里面的观察者模式方法,能完全理解还需要实战的经验。
观察者模式的类图:
在最基础的观察者模式中,包括以下四个角色:
用实例说话
这里我们的需求是可以动态添加或是移除一个关于气象的显示布告板。而这个布告板也是可以动态更新显示数据的。
比方说,目前有三个布告板:当前天气、预报、统计数据布告板。当我们气象站中的相关数据发生变化时,我们就去更新所有这些布告板的数据。你可能会说这个简单啊,只要在每个布告板上添加一个时间触发器就好了啊。每个布告板又是相互独立的,所以还可以添加上多线程操作。对于这个问题,这样写是可以的。可是,如果现在需求里需要新增一个新的布告板,展示的是不同的内容。于是,新的布告板又要新重编写所有逻辑,气象站里也要新增一些逻辑操作来支持这种新的需求。
这样是不是有点麻烦?要是我们的气象站对象可以一直不变就好了,因为气象站可能会是一个服务器端的代码。气象站里返回的数据是一些性质不变的数据。这里就是温度、湿度、气压。
主题每次更新都去更新这三个值,然后去通知所有的观察者说现在数据有变化,你们现在都刷新一下布告板吧。于是,观察者们就开始更新布告板的显示。
拿经典的气象站设计说明,
被观察者是接口Subject
观察者是接口Observer
具体的被观察者是WeatherData
具体的观察者是当前天气、预报、统计数据布告板
理解:
被观察者里面有个列表用来存观察者,控制台实例一个观察者(如预报板)的时候,注册这个观察者(就是把观察者加入到被观察者的列表里面去)。观察者内部有一个update方法,可供被观察者调用,更改信息。被观察者内部可以增加观察者,删除观察者,给观察者发通知。当数据改变的时候,只需调用被观察者的通知函数notify(),遍历观察者列表,给每个观察者发送通知,调用观察者的update函数即可。
被观察者接口
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
观察者接口
public interface Observer {
public void update();
}
代码部分:
接口
/**
* Created by konghao on 2017/12/1.
* 展示接口
*/
public interface DisplayElement {
public void display();
}
/**
* Created by konghao on 2017/12/1.
* 观察者接口
*/
public interface Observer {
public void update(float temp,float humidity,float pressure);
}
/**
* Created by konghao on 2017/12/1.
* 被观察者接口
*/
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
被观察者类
/**
* Created by konghao on 2017/12/1.
* 具体主题类,被观察者
*/
public class WeatherData implements Subject{
private ArrayList observers;
private float temperature; //温度
private float humidity; //湿度
private float pressure; //气压
public WeatherData(){
observers = new ArrayList();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
/**
* 更新通知所有的观察者
*/
@Override
public void notifyObserver() {
for(int i = 0;i < observers.size();i++){
Observer observer = (Observer) observers.get(i);
observer.update(temperature,humidity,pressure);
}
}
public void measurementsChanged(){
notifyObserver();
}
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
具体观察者类,其一
/**
* Created by konghao on 2017/12/1.
* 预报
*/
public class ForecastDisplay implements Observer,DisplayElement{
private float temperature;//温度
private float humidity;//湿度
private float pressure;//气压
private Subject weatherData = null;
public ForecastDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
display();
}
@Override
public void display() {
System.out.print("Forecast:");
//简单的预测天气算法
if(temperature>=86){
System.out.print("It will be hot today!(by 150)\n");
}else if(temperature<=50){
System.out.print("It will be very cold today!(by 150)\n");
}else if(temperature<86&temperature>50){
System.out.print("More of the same!(by 150)\n");
}
}
}
输出