观察者模式

包括两个操作,观察者订阅自己关心的主题和主题有数据变化后通知观察者们。

首先,需要定义主题,每个主题需要持有观察者列表的引用,用于在数据变更的时候通知各个观察者:

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
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
// 数据已变更,通知观察者们
notifyAllObservers();
}

// 注册观察者
public void attach(Observer observer) {
observers.add(observer);
}

// 通知观察者们
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}

定义观察者接口:

1
2
3
4
5
public abstract class Observer {
protected Subject subject;

public abstract void update();
}

定义具体的几个观察者类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class BinaryObserver extends Observer {
// 在构造方法中进行订阅主题
public BinaryObserver(Subject subject) {
this.subject = subject;
// 通常在构造方法中将 this 发布出去的操作一定要小心
this.subject.attach(this);
}

// 该方法由主题类在数据变更的时候进行调用
@Override
public void update() {
String result = Integer.toBinaryString(subject.getState());
System.out.println("订阅的数据发生变化,新的数据处理为二进制值为:" + result);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
String result = Integer.toOctalString(subject.getState());
System.out.println("订阅的数据发生变化,新的数据处理为八进制值为:" + result);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class HexObserver extends Observer {
public HexObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
String result = Integer.toHexString(subject.getState()).toUpperCase();
System.out.println("订阅的数据发生变化,新的数据处理为十六进制值为:" + result);
}
}

客户端使用:

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String[] args) {
// 先定义一个主题
Subject subject = new Subject();
// 定义观察者
new BinaryObserver(subject);
new OctalObserver(subject);
new HexObserver(subject);
// 模拟数据变更,这个时候,观察者们的 update 方法将会被调用
subject.setState(11);
}
}

output:

1
2
3
订阅的数据发生变化,新的数据处理为二进制值为:1011
订阅的数据发生变化,新的数据处理为八进制值为:13
订阅的数据发生变化,新的数据处理为十六进制值为:B

参考