设计模式之观察者模式

观察者模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖于它的对象都能得到通知并可以自动作出处理

比如说:报纸的订阅,一旦订阅,当有新的报纸发布,所有的订阅者都会收到消息

基本概念

组成

  1. 观察者:Observer,也叫订阅者,即Subscriber(Rxjava)
  2. 被观察者:Observable

java中的体现

java中提供了ObservableObserve接口供我们快速实现这种模式

代码实现

  • 假如有下面这样的一个实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Weather {
private String description;

public Weather(String description) {
this.description = description;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

@Override
public String toString() {
return "Weather{" +
"description='" + description + '\'' +
'}';
}
}
  • 定义观察者接口(因为观察者可能有很多类型,所以我们定义成一个接口,如果想要订阅这个事件,实现这个接口即可,另外一般订阅之后,在实现接口中的方法的参数中会拿到发布的数据,数据的类型不固定所以这个观察者接口需要定义范型)
1
2
3
public interface Observer<T> {
void onUpdate(Observable<T> observable,T data);
}
  • 定义被观察者对象(可以设计成单例模式,类似EventBus,内部维持一个集合,用来保存观察者对象;register方法和unregister方法用来将观察者对象从集合中添加和移除出来,post方法用来发布,循环遍历集合,依次调用观察者的相关回调方法,并将发布的参数传入)
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
51
52
53
54
package com.it.fengan.designpattern.pattern;

import java.util.ArrayList;
import java.util.List;

/**
* Created by fengan on 2017/12/12.
* email:fengan1102@gmail.com
*/

public class Observable<T> {

private static Observable observable;

private Observable() {

}

public static Observable getInstance() {
if (observable == null) {
synchronized (Observable.class) {
if (observable == null) {
observable = new Observable();
}
}
}
return observable;
}

private List<Observer> observers = new ArrayList<>();

public void register(Observer<T> observer) {
if (observer == null) {
throw new RuntimeException("observer error");
}

synchronized (Observable.class) {
if (!observers.contains(observer)) {
observers.add(observer);
}
}
}

public void unregister(Observer<T> observer) {
observers.remove(observer);
}

public void post(T data) {
for (Observer observer : observers) {
observer.onUpdate(this, data);
}
}

}
  • 注册和反注册过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Test
public void testObserver() {
Observer<Weather> objectObserver1 = new Observer<Weather>(){

@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
Log.e("testObserver", "objectObserver1:data=" + data.toString());
}
};
Observer<Weather> objectObserver2 = new Observer<Weather>(){
@Override
public void onUpdate(Observable<Weather> observable, Weather data) {
Log.e("testObserver", "objectObserver2:data=" + data.toString());
}
};
Observable observable = Observable.getInstance();
observable.register(objectObserver1);
observable.register(objectObserver2);
Weather weather = new Weather("晴天");
observable.post(weather);
observable.unregister(objectObserver2);
observable.post(weather);
}

logcat输出

1
2
3
12-19 15:18:44.780 2004-2036/? E/testObserver: objectObserver1:data=Weather{description='晴天'}
12-19 15:18:44.780 2004-2036/? E/testObserver: objectObserver2:data=Weather{description='晴天'}
12-19 15:18:44.780 2004-2036/? E/testObserver: objectObserver1:data=Weather{description='晴天'}

Android中的应用

  • 一对一的观察者(一般称之为回调,只有一个观察者)
1
2
3
4
5
6
7
Button btn=new Button(this);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("TAG","click");
}
});
  • 只要是set系列的设置监听器的方法最多都只能算回调,但是有一些监听器式add进去的,这种就是观察者模式了(比如RecyclerView中的addOnScrollListener方法)

RecycleView.java

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


private List<OnScrollListener> mScrollListeners;

/**
* Add a listener that will be notified of any changes in scroll state or position.
*
* <p>Components that add a listener should take care to remove it when finished.
* Other components that take ownership of a view may call {@link #clearOnScrollListeners()}
* to remove all attached listeners.</p>
*
* @param listener listener to set or null to clear
*/
public void addOnScrollListener(OnScrollListener listener) {
if (mScrollListeners == null) {
mScrollListeners = new ArrayList<>();
}
mScrollListeners.add(listener);
}

/**
* Remove a listener that was notified of any changes in scroll state or position.
*
* @param listener listener to set or null to clear
*/
public void removeOnScrollListener(OnScrollListener listener) {
if (mScrollListeners != null) {
mScrollListeners.remove(listener);
}
}

/**
* Remove all secondary listener that were notified of any changes in scroll state or position.
*/
public void clearOnScrollListeners() {
if (mScrollListeners != null) {
mScrollListeners.clear();
}
}
  • Android的广播机制,其本质也是观察者模式,这里为了简单方便,直接拿本地广播的代码说明,即LocalBroadcastManager
1
2
3
4
LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
localBroadcastManager.unregisterReceiver(BroadcastReceiver receiver);
localBroadcastManager.sendBroadcast(Intent intent)
  • 开源库(EventBus)

观察者模式的三个典型方法它都具有,即注册,取消注册,发送事件

1
2
3
4
EventBus.getDefault().register(Object subscriber);
EventBus.getDefault().unregister(Object subscriber);

EventBus.getDefault().post(Object event);
  • 重量级的库,它就是RxJava

创建一个被观察者

1
2
3
4
5
6
7
8
9
Observable<String> myObservable = Observable.create(  
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted();
}
}
);

创建一个观察者,也就是订阅者

1
2
3
4
5
6
7
8
9
10
Subscriber<String> mySubscriber = new Subscriber<String>() {  
@Override
public void onNext(String s) { System.out.println(s); }

@Override
public void onCompleted() { }

@Override
public void onError(Throwable e) { }
};

观察者进行事件的订阅

1
myObservable.subscribe(mySubscriber);
文章目录
  1. 1. 基本概念
    1. 1.1. 组成
    2. 1.2. java中的体现
    3. 1.3. 代码实现
  2. 2. Android中的应用