定义
观察者模式又名发布-订阅模式,定义了对象之间的一对多依赖,多个对象同时监听一个对象,当被监听对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新,被监听对象称为主题suject,监听对象称为观察者observer。
简单来说,observer必须实现update方法,来接收suject状态变化时的通知及更新。suject维护一个observer列表,在状态变化时会逐个的调用observer的update方法来通知、更新observer,为此,suject须提供注册(添加observer到列表)、删除、通知更新三个方法。
- 观察者模式又分为两种模式:push pull
- push是指suject在状态变化时将所有的状态信息都发给observer
- pull则是suject通知observer更新时,observer获取自己感兴趣的状态。
- 两种模式在实现上的区别
- push模式下,observer的update方法接收的是状态信息
- pull模式下,update方法接收的是suject对象,这种情况下,suject须提供状态信息的get方法,让observer可以获取自己感兴趣的信息。
- 两种模式的优劣
push模式要求suject必须了解observer需要的状态,pull则是observer按需获取;push模式下observer的update方法的参数是具体的状态信息,发生变化时必须要重写update方法,pull模式则是将suject对象本身传给update,是最大的参数集合。
push模式实现
suject超类
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
41package observer.push;
import java.util.LinkedList;
import java.util.List;
/**
* 推模式主题超类,能够注册、删除、数据变动时通知关注者
* @author sky
*
*/
public abstract class Subject {
/**
* 观察者名单
*/
private List<Observer> list = new LinkedList<>();
/**
* 注册观察者
* @param o 观察者
*/
public void addObserver(Observer o){
list.add(o);
}
/**
* 删除观察者
* @param o 观察者
*/
public void deleteObserver(Observer o){
int i = list.indexOf(o);
if (i>-1) {
list.remove(i);
}
}
/**
* 通知观察者
*/
public void notifyObservers(String state){
for (Observer o:list) {
o.update(state);
}
}
}observer接口
1
2
3
4
5
6
7
8
9
10
11package observer.push;
/**
* 推模式观察者接口
* @author sky
*
*/
public interface Observer {
public void update(String state);
}suject具体实现类
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
39package observer.push;
public class ConcreteSubject extends Subject {
/**
* 状态
*/
public String state;
/**
* 状态是否改变的标志
*/
public boolean isChanged = false;
/**
* 状态改变后,通知观察者
*/
public void change(){
if (isChanged) {
this.notifyObservers(state);
}
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
isChanged = true;
}
public boolean isChanged() {
return isChanged;
}
public void setChanged(boolean isChanged) {
this.isChanged = isChanged;
}
}observ具体实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package observer.push;
/**
* 推模式观察者实现类
* @author sky
*
*/
public class ConcreteObserver implements Observer {
public String name;
public ConcreteObserver(String n){
name=n;
}
public void update(String state) {
System.out.println(name+" update new state:"+state);
}
}测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package observer.push;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer o1 = new ConcreteObserver("张山");
Observer o2 = new ConcreteObserver("李四");
subject.addObserver(o1);
subject.addObserver(o2);
System.out.println("准备:");
subject.setState("上班了");
subject.change();
subject.setState("下班了");
subject.change();
}
}输出
1
2
3
4
5准备:
张山 update new state:上班了
李四 update new state:上班了
张山 update new state:下班了
李四 update new state:下班了
pull模式实现
suject超类
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
41package observer.pull;
import java.util.LinkedList;
import java.util.List;
/**
* 拉模式主题超类,能够注册、删除、数据变动时通知关注者
* @author sky
*
*/
public abstract class Subject {
/**
* 观察者名单
*/
private List<Observer> list = new LinkedList<>();
/**
* 注册观察者
* @param o 观察者
*/
public void addObserver(Observer o){
list.add(o);
}
/**
* 删除观察者
* @param o 观察者
*/
public void deleteObserver(Observer o){
int i = list.indexOf(o);
if (i>-1) {
list.remove(i);
}
}
/**
* 通知观察者
*/
public void notifyObservers(){
for (Observer o:list) {
o.update(this);
}
}
}observer接口
1
2
3
4
5
6
7
8
9
10
11package observer.pull;
/**
* 拉模式观察者接口
* @author sky
*
*/
public interface Observer {
public void update(Subject s);
}suject具体实现类
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
39package observer.pull;
public class ConcreteSubject extends Subject {
/**
* 状态
*/
public String state;
/**
* 状态是否改变的标志
*/
public boolean isChanged = false;
/**
* 状态改变后,通知观察者
*/
public void change(){
if (isChanged) {
this.notifyObservers();
}
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
isChanged = true;
}
public boolean isChanged() {
return isChanged;
}
public void setChanged(boolean isChanged) {
this.isChanged = isChanged;
}
}observer具体实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package observer.pull;
/**
* 拉模式观察者实现类
* @author sky
*
*/
public class ConcreteObserver implements Observer {
public String name;
public ConcreteObserver(String n){
name=n;
}
public void update(Subject s) {
String state = ((ConcreteSubject)s).getState();
System.out.println(name+" update new state:"+state);
}
}测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package observer.pull;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer o1 = new ConcreteObserver("张山");
Observer o2 = new ConcreteObserver("李四");
subject.addObserver(o1);
subject.addObserver(o2);
System.out.println("pull模式准备:");
subject.setState("上班了");
subject.change();
subject.setState("下班了");
subject.change();
}
}输出
1
2
3
4
5pull模式准备:
张山 update new state:上班了
李四 update new state:上班了
张山 update new state:下班了
李四 update new state:下班了