设计模式之观察者模式

设计模式之观察者模式

        观察者模式感觉是23种设计模式之中最简单的一种,当你需要获取一个变化的对象的部分信息时,可以考虑使用这种设计模式,它可以在你关注的对象改变时,及时的通知到你,并将你关心的值也传给你.观察者模式适用于类似订阅/发布的地方.

        被观察主体实现自Subject接口

package com.yczuoxin.pattern.subject;

import com.yczuoxin.pattern.observer.Observer;

public interface Subject {
    void registerObserver(@NotNull Observer observer);

    void removeObserver(@NotNull Observer observer);

    void notifyObserver();
}

        观察者主题实现自Observer接口

package com.yczuoxin.pattern.observer;

public interface Observer {

    void update(float temperature, float humidity, float pressure);
}

        例如常见的气象公布板WeatherData实体类实现

package com.yczuoxin.pattern.subject;

import com.sun.istack.internal.NotNull;
import com.yczuoxin.pattern.observer.Observer;

import java.util.ArrayList;

public class WeatherData implements Subject {

    private ArrayList<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(@NotNull Observer observer) {
        observers.add(observer);
    }

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

    @Override
    public void notifyObserver() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurements();
    }

    public void measurements(){
        notifyObserver();
    }
}

        编写观察者对象输出语句的接口ElementDisplay

package com.yczuoxin.pattern.observer;

public interface ElementDisplay {
    void display();
}

        编写第一个观察者对象CurrentConditionDisplay实体类,该类实现Obsever接口以及ElementDisplay接口,该实体类观察气象公布板上所有的信息

package com.yczuoxin.pattern.observer;

import com.yczuoxin.pattern.subject.Subject;

public class CurrentConditionsDisplay implements Observer, ElementDisplay {

    private Subject weatherData;
    private float temperature;
    private float humidity;
    private float pressure;

    public CurrentConditionsDisplay(Subject weatherData){
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("当前温度为:" + temperature + "℃"+ "\n" +
                            "当前湿度为:" + humidity + "%" + "\n" +
                            "当前大气压为:" + pressure + "Pa");
    }


    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }
}

        编写第二个观察者对象GeneralDisplay实体类,该类实现Obsever接口以及ElementDisplay接口,该实体类观察气象公布板上部分的信息

package com.yczuoxin.pattern.observer;

import com.yczuoxin.pattern.subject.Subject;

public class GeneralDisplay implements Observer,ElementDisplay {

    private Subject weatherData;
    private float temperature;
    private float humidity;

    public GeneralDisplay(Subject weatherData){
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("当前温度为:" + temperature + " ℃"+ "\n" +
                "当前湿度为:" + humidity + " %" + "\n");
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }
}

        使用测试类去测试我们写的代码

package com.yczuoxin.pattern;

import com.yczuoxin.pattern.observer.CurrentConditionsDisplay;
import com.yczuoxin.pattern.observer.GeneralDisplay;
import com.yczuoxin.pattern.subject.Subject;
import com.yczuoxin.pattern.subject.WeatherData;

public class ObserverTest {
    public static void main(String[] args) {
        Subject weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay = 
                new CurrentConditionsDisplay(weatherData);
        GeneralDisplay generalDisplay = new GeneralDisplay(weatherData);
        ((WeatherData) weatherData).setMeasurements(32.5f,45.2f,103.2f);
    }
}
当前温度为:32.5 ℃
当前湿度为:45.2 %
当前大气压为:103.2 Pa
当前温度为:32.5 ℃
当前湿度为:45.2 %

        结果可以看到当公布板的值改变后,两个观察者对象实体立即获取了公布板上公布的所需要的值.这就是观察者模式要达到的效果.观察者模式的主体接口需要有三个主方法:

         1.注册观察者的registerObserver();

         2.通知观察者主体信息已被修改的notifyObserver(),该方法如果传入参数就是主动推送的的方式,也可以提供getter,setter方法让观察者自己去拉取数据.

         3.移除观察者的removeObserver();

        而观察者需要维护主体,并有一个主方法update();

        JDK对于观察者模式也提供有自己的方法,被观察者要继承自Observable抽象类,而观察者则需要继承自Observer抽象类.Observable抽象类中维护了一个私有boolean变量changed,只有当changed为true时才触发通知观察者,这样做使得通知观察者的时机更加灵活,是值得借鉴的一个点,但是由于JDK提供的这两个皆为抽象类,只得去继承,根据java的单继承的原则,会对扩展该方法产生限制,所以使用的时候要斟酌清楚其中的利弊.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值