观察者模式
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并且被自动更新
使用场景
- 关联行为场景,注意不是“组合”关系
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制
观察者模式的写法
UML图如下:
- Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
- Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
- ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
定义抽象观察者:
/**
* 抽象观察者
*/
public interface Observer {
public void notify(String message);
}
创建具体观察者:
/**
* 具体观察者
*/
public class ConcrereObserver implements Observer {
private String name;
public ConcrereObserver(String name) {
this.name = name;
}
@Override
public void notify(String message) {
System.out.println(message+"更新");
}
}
定义抽象被观察者:
/**
* 抽象观察者
*/
public interface Subject {
/**
* 添加订阅者
*/
public void register(Observer observer);
/**
* 删除订阅者
*/
public void unRegister(Observer observer);
/**
* 通知更新
*/
public void notify(String message);
}
创建具体被观察者:
public class ConcrereSubject implements Subject {
/**
* 具体被观察者中维护一个集合,用于保存观察者
*/
private List<Observer> observerList = new ArrayList<>();
//添加观察者
@Override
public void register(Observer observer) {
observerList.add(observer);
}
//移除观察者
@Override
public void unRegister(Observer observer) {
observerList.remove(observer);
}
//通知所有观察者更新
@Override
public void notify(String message) {
for (Observer observer : observerList) {
observer.notify(message);
}
}
}
值得注意的是在更新的时候是遍历结合,调用观察者的更新方法,这个过程是同步的,若是在执行某个方法的时候阻塞,则整个系统会出现卡顿的情况。
Rxjava结构图
Rxjava 1.x
Rxjava 2.x
这里我们可以看到Rxjava中主要的内容分为两块,其一是观察者模式的应用体现,其二是线程控制的模块,我们借助Rxjava 2.x来具体说明。首先在Rxjava 2.x中作为被观察者角色的有5中类型,用法非常相似,在上游发射数据,在下游消费数据,这一点上与Rxjava 1.x中有些不同,比如在Rxjava 1.x中Subscriber 既能发射数据,又能消费数据,充当观察者和被观察者。在2.x 中 把它拆解成了2个接口。ObservableEmitter专门用来发射数据,Consumer 专门用来消费数据,接下来我们就着这5种类型来分别说明
Observable
使用场景:
数据流最长不超过1000个元素,即随着时间的流逝,应用没有机会报OOME(OutOfMemoryError)错误。
处理诸如鼠标移动或触摸事件之类的GUI事件
//创建观察者
Observer<String> mObserver = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("tag1","onSubscribe");
}
@Override
public void onNext(String s) {
Log.d("tag1","onNext:"+s);
}
@Override
public void onError(Throwable e) {
Log.d("tag1","onError");
}
@Override
public void onComplete() {
Log.d("tag1","onComplete");
}
};
//创建被观察者
Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("寒塘渡鹤影");
emitter.onNext("冷月葬花魂");
emitter.onNext("鸟宿池边树");
emitter.onNext("僧敲月下门");
emitter.onError(new Throwable("不是同一首诗!"));
}
});
//订阅
observable.subscribe(mObserver);
这里我们值得注意的是,在Rxjava 1.x中提供Action1等接口,用来实现自定义的消息回调,同样在Rxjava 2.x中提供Consumer接口来实现同样的效果,例如:
//定义onNext
Consumer<String> consumerNext = new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("tag","定义onNext: "+s);
}
};
//定义error
Consumer<Throwable> throwableConsumer = new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.d("tag","定义error: "+throwable.getMessage());
}
};
//定义complete
Action completeAction = new Action() {
@Override
public void run() throws Exception {
Log.d("tag","定义complete: ");
}
};
//定义subscribe
Consumer<Disposable> subscribeConsumer = new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
Log.d("tag","定义subscribe: ");
}
};
//订阅
observable.subscribe(consumerNext,throwableConsumer,completeAction,subscribeConsumer);
Flowable
使用场景:
- 处理超过10K+ 的元素流
- 从磁盘读取(解析文件)
- 从数据库读取数据
- 从网络获取数据流
Flowable.create(new FlowableOnSubscribe<String>() {
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
emitter.onNext("你好");
emitter.onNext("哈哈");
emitter.onNext("呵呵");
emitter.onNext("拉阿拉");
emitter.onComplete();
}
}, BackpressureStrategy.DROP) //指定背压策略
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
//1、onSubscribe 是2.x新添加的方法,在发射数据前被调用,相当于1.x的onStart方法
//2、参数为 Subscription ,Subscription 可用于向上游请求发射多少个元素,也可用于取笑请求
//3、必须要调用Subscription 的request来请求发射数据,不然上游是不会发射数据的。
Log.d("tag1","onSubscribe");
s.request(4);
}
@Override
public void onNext(String s) {
Log.d("tag1","onNext : "+s);
}
@Override
public void onError(Throwable t) {
Log.d("tag1","onError");
}
@Override
public void onComplete() {
Log.d("tag1","onComplete");
}
});
onSubscribe 回调方法中,参数是Subscription而不是Disposable,在RxJava 2.x 中,订阅的管理换成了Disposable,但是Flowable使用的是Subscription,这个Subscription不是1.x 版本中的Subscription,虽然它有取消订阅的能力。主要用于请求上游元素和取消订阅
Single
使用场景:
只用于发射一个数据
Single.create(new SingleOnSubscribe<Boolean>() {
@Override
public void subscribe(SingleEmitter<Boolean> emitter) throws Exception {
emitter.onSuccess(true);
}
}).observeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("tag2","onSubscribe::"+ d.isDisposed());
}
@Override
public void onSuccess(Boolean aBoolean) {
Log.d("tag2","onSuccess::"+aBoolean.toString());
}
@Override
public void onError(Throwable e) {
Log.d("tag2","onError::"+e.getMessage());
}
});
}
Single只发射一个元素,所以没有complete 方法,不像Observable或者Flowable,数据发射完成之后,需要调用complete告诉下游已经完成
Completable
使用场景:
不会发射数据,只会给下游发送一个信号。回调 onComplete方法
Completable.create(new CompletableOnSubscribe(){
@Override
public void subscribe(CompletableEmitter emitter) throws Exception {
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver(){
@Override
public void onSubscribe(Disposable d) {
Log.d("tag3","onSubscribe::"+ d.isDisposed());
}
@Override
public void onComplete() {
Log.d("tag3","onComplete::");
}
@Override
public void onError(Throwable e) {
Log.d("tag3","onError::");
}
});
Maybe
使用场景:
结果不确定,可能发射0(Completable)或1(Single) 个元素,或者收到一个Error信号
Maybe.create(new MaybeOnSubscribe<Boolean>() {
@Override
public void subscribe(MaybeEmitter<Boolean> emitter) throws Exception {
emitter.onSuccess(true);
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new MaybeObserver<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("tag4","onSubscribe::");
}
@Override
public void onSuccess(Boolean aBoolean) {
Log.d("tag4","onSuccess::"+aBoolean);
}
@Override
public void onError(Throwable e) {
Log.d("tag4","onError::"+e.getMessage());
}
@Override
public void onComplete() {
Log.d("tag4","onComplete::");
}
});
Maybe是Single和Completable的结合,需要注意的是onSuccess和onComplete方法只会执行其中一个,这不同于Observable和Flowable最后是以onComplete()结尾
https://www.jianshu.com/p/0cd258eecf60
https://github.com/ReactiveX/RxJava/wiki/What’s-different-in-2.0
https://blog.csdn.net/SilenceOO/article/details/77683875