Observer模式

观察者模式中也叫监听者模式,顾名思义,Observer模式 中登场的角色有 观察者被观察者。可将其抽象为 Observer 接口和 Subject 抽象类。

1
2
3
4
5
6
package com.company;

//Observer 接口,update方法即为被观察的对象某一状态改变时触发的动作。
public interface Observer {
public abstract void update ( Subject subject );
}
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
package com.company;

import java.util.ArrayList;
import java.util.Iterator;

public abstract class Subject {
private ArrayList observers = new ArrayList(); //保存观察者

public void addObserver ( Observer observer ){
observers.add( observer );
} //注册

public void delete ( Observer observer ){
observers.remove( observer );
} //删除

public void notifyObservers () { //发送通知
Iterator it = observers.iterator();

while (it.hasNext()){
Observer o = (Observer) it.next();
o.update( this );
}
}
//获取数值
public abstract int getNumber ();
//生成数值
public abstract void execute ();
}

定义了观察者接口和观察对象抽象类后,可以使用具体的对象来实现接口或继承抽象类,实现我们具体的需求。以下定义两个观察者A、观察者B、RandomSubject类 来实现一个最简单的观察者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.company;

public class ObserverA implements Observer {

@Override
public void update(Subject subject) {
System.out.println("ObserverA: " + subject.getNumber());

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.company;

public class ObserverB implements Observer {

@Override
public void update(Subject subject) {
System.out.println("ObserverB: " + subject.getNumber());

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

RandomSubject类 具体的被观察对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.company;

import java.util.Random;

public class RandomSubject extends Subject {
private Random random = new Random ();
private int number ;

@Override
public int getNumber() {
return number;
}

@Override
public void execute() {
for (int i = 0; i < 20; ++i) {
number = random.nextInt( 50 );
notifyObservers();
}
}
}

Main类 中测试我们的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.company;

public class Main {

public static void main(String[] args) {
Subject subject = new RandomSubject();

subject.addObserver( new ObserverB() );
subject.addObserver( new ObserverA() );

subject.execute();
}
}

输出如下,每次生成随机数时候,都会触发A、B观察者的 update 方法。在控制台中打印

Observer模式 有具体的被观察对象和具体的观察者。连接这两个角色的就是他们的接口(API)SubjectObserver。一方面 RandomSubject 并不知道自己被 ObserverAObserverB 所观察,二者只是确定实现了接口的方法。这在一定程度上实现了解耦,提高了复用性。

关于观察者模式,这只是实现的一个最简单的DEMO,也就是书上给的示例,关于观察者模式还有很多用途,比如 Laravel框架 中的事件监听等奇淫巧技,关于这一部分还要今后多加思考 Orz。

参考书目 《图解设计模式》