铁匠 铁匠
首页
收藏
java
架构之路
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
链接
  • 分类
  • 标签
  • 归档

专注、不予评判地关注当下
首页
收藏
java
架构之路
常用算法
  • Java
  • nginx
  • 系统运维
  • 系统安全
  • mysql
  • redis
参考文档
关于
链接
  • 分类
  • 标签
  • 归档
  • 概览

  • 设计模式

    • 软件设计原则
    • 创建型

    • 结构型

    • 行为型

      • 观察者模式
        • 不使用第三方类库实现
        • 使用guava实现
      • 模板方法
      • 策略模式
  • 高可用

  • 性能优化

  • 分布式

  • 网关

  • 流量治理

  • 数据治理

  • 云原生

  • 网络安全

  • 架构
  • 设计模式
  • 行为型
fengjx
2023-01-06
目录

观察者模式

观察者模式又叫发布订阅模式,通常用在事件监听和数据变更通知场景中。当一个对象状态发生改变时,所有依赖于它的对象都会得到变更通知,时一种对象间一对多关系。

案例:当天气发生变化时,电视台播放天气预告,手机推送天气消息。

# 不使用第三方类库实现

public interface Subject<M> {

    /**
     * 添加监听者
     */
    void register(Observer<M> observer);

    /**
     * 移除监听者
     */
    void unregister(Observer<M> observer);

    void notifyObservers();

    /**
     * 事件通知
     */
    void notifyObservers(M msg);

}

// 通用 Subject 封装
public class Observable<M> implements Subject<M> {

    /**
     * executor != null 时,异步通知
     */
    private final Executor executor;
    private final List<Observer<M>> observers;

    public Observable() {
        this.executor = null;
        this.observers = new CopyOnWriteArrayList<>();
    }

    public Observable(final Executor executor) {
        this.executor = executor;
        this.observers = new CopyOnWriteArrayList<>();
    }

    @Override
    public void register(final Observer<M> observer) {
        observers.add(observer);
    }

    @Override
    public void unregister(final Observer<M> observer) {
        observers.remove(observer);
    }

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

    @Override
    public void notifyObservers(M msg) {
        if (executor == null) {
            observers.forEach(item -> item.update(msg));
            return;
        }
        observers.forEach(item -> executor.execute(() -> item.update(msg)));
    }
}

// 具体 Subject 实现
public class Weather extends Observable<WeatherType> {

    private static final AtomicInteger curr = new AtomicInteger(0);

    public void weatherChange() {
        final WeatherType[] weatherTypes = WeatherType.values();
        WeatherType currentWeather = weatherTypes[curr.getAndIncrement() % weatherTypes.length];
        System.out.println("天气发生变化:" + currentWeather);
        notifyObservers(currentWeather);
    }
}

// 观察者
public interface Observer<M> {

    void update(M msg);

}

public class TvWeatherObserver implements Observer<WeatherType> {

    @Override
    public void update(final WeatherType msg) {
        System.out.println("电视台天气预告,当前天气:" + msg.getDescription());
    }
}

public class PhoneWeatherObserver implements Observer<WeatherType> {

    @Override
    public void update(final WeatherType msg) {
        System.out.println("手机推送,当前天气:" + msg.getDescription());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

测试类

public class WeatherApp {

    public static void main(String[] args) {
        Weather weather = new Weather();
        weather.register(new TvWeatherObserver());
        weather.register(new PhoneWeatherObserver());
        weather.weatherChange();
        weather.weatherChange();
        weather.weatherChange();
        weather.weatherChange();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 使用guava实现

public class GuavaWeather {

    private final EventBus bus = new EventBus("weather");
    private static final AtomicInteger curr = new AtomicInteger(0);

    public void register(final Object observer) {
        bus.register(observer);
    }

    public void unregister(final Object observer) {
        bus.unregister(observer);
    }

    public void weatherChange() {
        final WeatherType[] weatherTypes = WeatherType.values();
        WeatherType currentWeather = weatherTypes[curr.getAndIncrement() % weatherTypes.length];
        System.out.println("天气发生变化:" + currentWeather);
        bus.post(currentWeather);
    }
}

public class GuavaTvWeatherObserver {

    @Subscribe
    public void update(final WeatherType msg) {
        System.out.println("电视台天气预告,当前天气:" + msg.getDescription());
    }
}

public class GuavaPhoneWeatherObserver {

    @Subscribe
    public void update(WeatherType msg) {
        System.out.println("手机推送,当前天气:" + msg.getDescription());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

测试类

public class GuavaWeatherApp {
    public static void main(String[] args) {
        final GuavaWeather weather = new GuavaWeather();
        weather.register(new GuavaTvWeatherObserver());
        weather.register(new GuavaPhoneWeatherObserver());
        weather.weatherChange();
        weather.weatherChange();
        weather.weatherChange();
        weather.weatherChange();
        weather.weatherChange();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

EventBus源码可以查看https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/EventBus.java (opens new window)

另外guava还提供了异步支持AsyncEventBus (opens new window)

#观察者模式
代理模式
模板方法

← 代理模式 模板方法→

最近更新
01
策略模式
01-09
02
模板方法
01-06
03
代理模式
01-03
更多文章>
Theme by Vdoing | Copyright © 2016-2023 铁匠 | 粤ICP备15021633号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式