观察者模式
# 一、概述
观察者(Observer)模式其实是实现一种订阅机制,它定义了对象间一种一对多的依赖关系,使得当某个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
# 1.1 解决了什么问题
烟草公司对每个零售商每个月可以销售的香烟品牌和数量是限制的,因此很多小规模的零售商经常会出现供不应求的现象,村头的小卖部就是这样,经常会卖断货。但是村里的老烟鬼并不知道小卖部什么时候会补货,于是他们只能每天都往小卖部跑一趟问老板。更气人的是,好不容易有烟了,结果还是六七十块一包的华子,抽不起抽不起,白跑一趟。其实小卖部老板也烦求的很,每天中午睡觉的时候就被这些老烟鬼喊醒。
# 1.2 解决方案
为了保证自己自己不被打扰,于是小卖部老板建了个微信群,把这些老烟鬼拉到群里,有新货之后就在群里通知。其实就是发布订阅机制。
# 二、实现方式
# 2.1 角色
总的来说,观察者模式有两个角色:观察者与被观察者。
- Subject:抽象的被观察者,定义了观察者订阅和取消订阅的方法,以及状态发生变更时通知观察者的方法。
- ConcreteSubject:具体观察者,实现了 Subject 中的所有方法。
- Observer:抽象观察者,定义接受时间通知的接口。
- ConcreteObserver:具体观察者,实现了 Observer 中的方法。
# 2.2 代码
观察者接口:
public interface Observer {
void update(String message);
}
1
2
3
2
3
被观察者接口:
public interface Subject {
void subscribe(String topic, Observer observer);
void unsubscribe(String topic, Observer observer);
void notify(String topic);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
具体观察者:
public class Consumer implements Observer {
private String name;
public Consumer(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "收到:" + message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
具体被观察者:
/**
* 超市老板,具体的被观察者
*/
public class SupermarketOwner implements Subject {
Map<String, List<Observer>> listeners = new HashMap<>();
@Override
public void subscribe(String topic, Observer observer) {
List<Observer> observers = listeners.get(topic);
if (observers == null) {
observers = new ArrayList<>();
observers.add(observer);
listeners.put(topic, observers);
} else {
observers.add(observer);
}
}
@Override
public void unsubscribe(String topic, Observer observer) {
List<Observer> observers = listeners.get(topic);
if (observers == null) {
System.out.println("主题不存在");
} else {
observers.remove(observer);
}
}
@Override
public void notify(String topic) {
List<Observer> observers = listeners.get(topic);
if (observers != null) {
for (Observer observer : observers) {
observer.update(topic + "到货了");
}
}
}
}
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
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
客户端:
public class ObserverTest {
public static void main(String[] args) {
Subject subject = new SupermarketOwner();
subject.subscribe("黑兰州", new Consumer("王老二"));
subject.subscribe("黑兰州", new Consumer("王老三"));
subject.subscribe("利群", new Consumer("张老六"));
subject.subscribe("利群", new Consumer("张老七"));
subject.subscribe("利群", new Consumer("张老八"));
subject.subscribe("华子", new Consumer("村长"));
subject.notify("华子");
System.out.println("------------");
subject.notify("利群");
System.out.println("------------");
subject.notify("黑兰州");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
村长收到:华子到货了
------------
张老六收到:利群到货了
张老七收到:利群到货了
张老八收到:利群到货了
------------
王老二收到:黑兰州到货了
王老三收到:黑兰州到货了
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 三、源码中的应用
- java.util.Observer(opens new window)
- java.util.EventListener
上次更新: 2023/11/01, 03:11:44