线程安全的观察者模式

1. 创建观察者

/**
 * @Author jet
 * @Description 观察者模式
 * @Date 2022/4/6 
 * @Param 
 * @return 
 **/
public interface Observer {
    /**
     * @Author jet
     * @Description 更新
     * @Date 2022/4/6 
     * @Param [o, arg]
     * @return void
     **/
    void update(Subject subject, Object arg);
}

2.主题

package com.jetluo.patterns.chapter02.theadsafe;


/**
 * @Author jet
 * @Description //主题接口
 * @Date 2022/3/31
 * @Param
 * @return
 **/
public interface Subject {
    /**
     * @Author jet
     * @Description //订阅
     * @Date 2022/4/6
     * @Param [o]
     * @return void
     **/
    public void addObserver(Observer observer);

    /**
     * @Author jet
     * @Description //删除订阅
     * @Date 2022/3/31
     * @Param [o]
     * @return void
     **/
    public void removeObserver(Observer observer);
    
    /**
     * @Author jet
     * @Description //发布通知
     * @Date 2022/4/6 
     * @Param []
     * @return void
     **/
    public void notifyObservers();

    /**
     * @Author jet
     * @Description //发布通知
     * @Date 2022/4/6
     * @Param []
     * @return void
     **/
    public void notifyObservers(Object o);

}

3.主题实现

package com.jetluo.patterns.chapter02.theadsafe;


import java.util.HashSet;
import java.util.Set;

/**
 * @ClassName ThreadSafeSubject
 * @Description TODO
 * @Author jet
 * @Date 2022/4/6 13:59
 * @Version 1.0
 **/
public class ThreadSafeSubject implements Subject{

    private final Object MONITOR = new Object();

    private Set<Observer> observerSet;

    @Override
    public void addObserver(Observer observer) {
        if ( observer == null){
            return;
        }
        synchronized (MONITOR){
            if (observerSet == null) {
                observerSet = new HashSet<Observer>(1);
            }
            if (observerSet.add(observer) && observerSet.size() == 1){
                // some initialization when first observer added
            }
        }
    }

    @Override
    public void removeObserver(Observer observer) {
        if ( observer == null){
            return;
        }
        synchronized (MONITOR){
            if (observerSet!=null && observerSet.remove(observer) && observerSet.isEmpty()){
                //some cleanup when last observer removed
            }
        }
    }

    @Override
    public void notifyObservers() {
        notifyObservers(null);
    }

    @Override
    public void notifyObservers(Object object) {
        Set<Observer> observersCopy;
        synchronized (MONITOR){
            if (observerSet == null){
                return;
            }
            observersCopy = new HashSet<>(observerSet);
        }
        for (Observer observer:observersCopy){
            observer.update(this, object);
        }
    }
}

4. 使用

package com.jetluo.patterns.chapter02.theadsafe;


/**
 * @ClassName WeatherData
 * @Description 1.新建主题 或者叫可观测者
 * Observable 作用:追踪所有的观察者,并通知他们。
 * @Author jet
 * @Date 2022/4/1 22:51
 * @Version 1.0
 **/
public class WeatherData extends ThreadSafeSubject {
    private float temperature;
    private float humidity;
    private float pressure;


    public WeatherData() {

    }

    public void measurementsChanged() {
        // 1。先调用setChanged()方法,标记状态已经改变的事实。
        //  setChanged();
        // 2。调用notifyObservers()方法。通知观察者
        //    或者调用  notifyObservers(Object obj); 推数据给观察者。
        notifyObservers();

    }

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

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

4.1 显示接口

package com.jetluo.patterns.chapter02.theadsafe;

public interface DisployElement {
    /**
     * @Author jet
     * @Description //展示模版
     * @Date 2022/3/31
     * @Param []
     * @return void
     **/
    public void display();
}

package com.jetluo.patterns.chapter02.theadsafe;



/**
 * @ClassName CurrentConditionsDisplay
 * @Description 具体的观察者
 *  Observer 的update()方法,这个方法会被Observable主题notifyObservers调用。
 * @Author jet
 * @Date 2022/4/1 23:05
 * @Version 1.0
 **/
public class CurrentConditionsDisplay implements Observer, DisployElement {

    ThreadSafeSubject subject;
    private float temperature;
    private float humidity;

    public CurrentConditionsDisplay(ThreadSafeSubject subject){
        this.subject = subject;
        subject.addObserver(this);
    }

    @Override
    public void display() {
        System.out.println("Current conditions: " + temperature
                + "F degrees and " + humidity + "% humidity");
    }
    /**
     * @Author jet
     * @Description //更新观察者数据。
     * @Date 2022/4/2
     * @Param [o, arg]
     * @return void
     **/
    @Override
    public void update(Subject subject, Object arg) {
        if (subject instanceof WeatherData){
            WeatherData weatherData =(WeatherData) subject;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            display();
        }
    }
}

package com.jetluo.patterns.chapter02.theadsafe;


/**
 * @ClassName ForecastDisploy
 * @Description TODO
 * @Author jet
 * @Date 2022/3/31 22:36
 * @Version 1.0
 **/
public class ForecastDisplay implements Observer, DisployElement {

    private float currentPressure = 29.92f;

    private float lastPressure;

    public ForecastDisplay(ThreadSafeSubject subject) {
        subject.addObserver(this);
    }

    @Override
    public void display() {
        System.out.print("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } else if (currentPressure == lastPressure) {
            System.out.println("More of the same");
        } else if (currentPressure < lastPressure) {
            System.out.println("Watch out for cooler, rainy weather");
        }
    }

    @Override
    public void update(Subject subject, Object arg) {
        if (subject instanceof WeatherData) {
            WeatherData weatherData = (WeatherData) subject;
            lastPressure = currentPressure;
            currentPressure = weatherData.getPressure();
            display();
        }
    }
}

5.实现

package com.jetluo.patterns.chapter02.theadsafe;


/**
 * @ClassName WeatherData
 * @Description 1.新建主题 或者叫可观测者
 * Observable 作用:追踪所有的观察者,并通知他们。
 * @Author jet
 * @Date 2022/4/1 22:51
 * @Version 1.0
 **/
public class WeatherData extends ThreadSafeSubject {
    private float temperature;
    private float humidity;
    private float pressure;


    public WeatherData() {

    }

    public void measurementsChanged() {
        // 1。先调用setChanged()方法,标记状态已经改变的事实。
        //  setChanged();
        // 2。调用notifyObservers()方法。通知观察者
        //    或者调用  notifyObservers(Object obj); 推数据给观察者。
        notifyObservers();

    }

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

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

6. 测试

package com.jetluo.patterns.chapter02.theadsafe;


/**
 * @ClassName WeatherStation
 * @Description TODO
 * @Author jet
 * @Date 2022/4/6 15:27
 * @Version 1.0
 **/
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData);
       // StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值