Java设计模式十:观察者模式(Observer)
观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
它将观察者和被观察者的对象分离开。提高了应用程序的可维护性和重用性。
实现观察者模式有很多形式,一种是“注册---通知---撤销注册”的形式。
观察者Observer:所有潜在的观察者必须实现观察者接口,这个接口只有update方法,当主题改变时,它被调用。
具体观察者ConcreteObserver: 具体观察者可以是任何实现了Observer接口的类。观察者必须注册具体主题,一边接收更新。
可观察者Subject: 主题接口,即可观察者Observable,对象使用此接口注册为观察者,或者把自己从观察者中删除,每个主题可以有多个观察者。
具体可观察者ConcreteSubject: 一个具体主题实现了主题接口,除了注册和撤销之外,具体主题还实现了notifyObservers()方法,这个方法用来在主题状态改变时更新所有观察者。具体主题也可能有设置和获取状态的方法。
类图:
//实例:
public interface Observer
{
public void update(float temprature);
}
public class ConcreteObserver implements Observer
{
private float temperature;
private final Subject subject;
public ConcreteObserver(final Subject subject)
{
this.subject = subject;
this.subject.registerObserver(this);
}
public float getTemperature()
{
return temperature;
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
}
@Override
public void update(final float temperature)
{
this.temperature = temperature;
}
}
public interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public class ConcreteSubject implements Subject
{
private final List<Observer> observers;
private float temperature;
public float getTemperature()
{
return temperature;
}
private void temperatureChanged()
{
this.notifyObservers();
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
this.temperatureChanged();
}
public ConcreteSubject()
{
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(final Observer o)
{
observers.add(o);
}
@Override
public void removeObserver(final Observer o)
{
if (observers.indexOf(o) >= 0)
{
observers.remove(o);
}
}
@Override
public void notifyObservers()
{
for (final Observer o : observers)
{
o.update(temperature);
}
}
}
public class Client
{
public static void main(final String[] args)
{
final ConcreteSubject sb = new ConcreteSubject();
sb.setTemperature((float) 20.00);
final Observer o = new ConcreteObserver(sb);
sb.setTemperature((float) 21.00);
}
}
观察者模式的应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
观察者模式的优点:
1、 Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、 Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
观察者模式的缺陷:
1、 松偶合导致代码关系不明显,有时可能难以理解。(废话)
2、 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)
JavaJava内置的观察者模式:
如何实现简单的观察者模式
接下来我们实现壹個简单的被观察者类 ExampleObservable ,代码如下:
1
2
3
4
5
6
7
8
9
10
11
|
import java.util.Observable;
public class ExampleObservable extends Observable {
int data = 0 ;
public void setData( int data){
this .data = data;
this .setChanged(); //标记此 Observable对象为已改变的对象
this .notifyObservers(); //通知所有的观察者
}
} |
再实现壹個观察者类 ExampleObserver,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.util.Observable;
import java.util.Observer;
public class ExampleObserver implements Observer {
//有被观察者发生变化,自动调用对应观察者的update方法
@Override
public void update(Observable object, Object argument) {
//通过强制类型转换获取被观察者对象
ExampleObservable example = (ExampleObservable)object;
System.out.println( "example.data changed, the new value of data is " + example.data);
}
} |
1
2
3
4
5
6
7
8
9
10
|
public class Main {
public static void main(String[] args) {
ExampleObservable example = new ExampleObservable();
example.addObserver( new ExampleObserver()); //给example这个被观察者添加观察者,允许添加多個观察者
example.setData( 2 );
example.setData(- 5 );
example.setData( 9999 );
}
} |
运行之后在控制台输出如下结果:
1
2
3
|
example.data changed, the new value of data is 2
example.data changed, the new value of data is - 5
example.data changed, the new value of data is 9999
|
通过输出结果我们可以了解到,当 ExampleObservable 类的实例 example 的成员变量 data 的值发生改变时,ExampleObserver 对象都能够监测到,然后调用 update() 方法打印壹句话到控制台,说明以上的结果是符合我们预期的。
既是观察者又是被观察者
对于壹個类而言,可以既是观察者又是被观察者,只要既继承 Observable 类,又实现 Observer 接口就可以了。接下来给出壹個类似的例子。例子中 ObserverA 和 ObserverB 既是观察者又是被观察者,它们互相监听着对方的改变。
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
|
//ObserverA.java import java.util.Observable;
import java.util.Observer;
public class ObserverA extends Observable implements Observer {
@Override
public void update(Observable object, Object arg) {
ObserverB observerB = (ObserverB)object;
System.out.println( "observerB changed, the new value of observerB.data is " + observerB.data);
this .setChanged();
this .notifyObservers();
}
} //ObserverB.java import java.util.Observable;
import java.util.Observer;
public class ObserverB extends Observable implements Observer {
int data = 0 ;
@Override
public void update(Observable object, Object arg) {
System.out.println( "ObserverB found that ObserverA changed..." );
}
public void setData( int data){
this .data = data;
this .setChanged();
this .notifyObservers();
}
} //Main.java import net.oschina.bairrfhoinn.multiply.ObserverA;
import net.oschina.bairrfhoinn.multiply.ObserverB;
public class Main {
public static void main(String[] args) {
ObserverA a = new ObserverA();
ObserverB b = new ObserverB();
a.addObserver(b);
b.addObserver(a);
b.setData( 2 );
}
} |
1
2
|
observerB changed, the new value of observerB.data is 2
ObserverB found that ObserverA changed... |
之所以会出现上述运行结果,最初 ObserverA 和 ObserverB 相互之间作为观察者与被观察者,但是 ObserverB 的实例 b 先调用的 setData() 方法,然后 ObserverA 的实例 a 观察到了这個变化,于是调用了本类的 update 方法打印出了第壹行,紧接着 ObserverA 的 update() 方法在方法体中声明了自己发生了变化,于是 ObserverB 观察了这個情况,也调用了自身的 update() 方法并打印了第二句话。