设计模式——观察者模式(气象站设计)

大三学习软件工程这门课,状态一直很懵,原因是其中所谓的设计模式、设计方法都是前人们一步步总结出来的,我既没有功力深厚的编程底子,也没有任何工程项目的经验,一介学生,学好不易。

以下博文部分摘自Q-WHai博客点击打开链接

下面总结一下设计模式里面的观察者模式方法,能完全理解还需要实战的经验。

观察者模式的类图:


在最基础的观察者模式中,包括以下四个角色:

  • 被观察者:从类图中可以看到,类中有一个用来存放观察者对象的Vector容器(之所以使用Vector而不使用List,是因为多线程操作时,Vector在是安全的,而List则是不安全的),这个Vector容器是被观察者类的核心,另外还有三个方法:attach方法是向这个容器中添加观察者对象;detach方法是从容器中移除观察者对象;notify方法是依次调用观察者对象的对应方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
  • 观察者:观察者角色一般是一个接口,它只有一个update方法,在被观察者状态发生变化时,这个方法就会被触发调用。
  • 具体的被观察者:使用这个角色是为了便于扩展,可以在此角色中定义具体的业务逻辑。
  • 具体的观察者:观察者接口的具体实现,在这个角色中,将定义被观察者对象状态发生变化时所要处理的逻辑。

用实例说话

这里我们的需求是可以动态添加或是移除一个关于气象的显示布告板。而这个布告板也是可以动态更新显示数据的。

  比方说,目前有三个布告板:当前天气、预报、统计数据布告板。当我们气象站中的相关数据发生变化时,我们就去更新所有这些布告板的数据。你可能会说这个简单啊,只要在每个布告板上添加一个时间触发器就好了啊。每个布告板又是相互独立的,所以还可以添加上多线程操作。对于这个问题,这样写是可以的。可是,如果现在需求里需要新增一个新的布告板,展示的是不同的内容。于是,新的布告板又要新重编写所有逻辑,气象站里也要新增一些逻辑操作来支持这种新的需求。

  这样是不是有点麻烦?要是我们的气象站对象可以一直不变就好了,因为气象站可能会是一个服务器端的代码。气象站里返回的数据是一些性质不变的数据。这里就是温度、湿度、气压。

  主题每次更新都去更新这三个值,然后去通知所有的观察者说现在数据有变化,你们现在都刷新一下布告板吧。于是,观察者们就开始更新布告板的显示。


拿经典的气象站设计说明,

被观察者是接口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");
        }
    }
}
输出













  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值