观察者模式(Observer Pattern)
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
观察者模式可以说用的比较多,比如天气预报服务,你订阅了本地的天气,每天一旦天气信息更新,它就会及时发送最新的天气信息。再比如,杂志的订阅,你只需向邮局订阅杂志,缴纳一定的费用,当有新的杂志时,邮局会自动将杂志送至你预留的地址。
以上例子有一个共同点,就是我们无需每时每刻关注我们感兴趣的东西,我们只需做的就是订阅感兴趣的事物,比如天气预报服务,杂志等,一旦我们订阅的事物发生变化,比如有新的天气预报信息,新的杂志等,被订阅的事物就会即时通知到订阅者,即我们。而这些被订阅的事物可以拥有多个订阅者,也就是一对多的关系。当然,严格意义上讲,这个一对多可以包含一对一,因为一对一是一对多的特例。
现在你反过头来看看观察者模式的定义,你是不是豁然开朗了。
观察者,我们称它为Observer,有时候我们也称它为订阅者,即Subscriber
被观察者,我们称它为Observable,即可以被观察的东西,有时候还会称之为主题,即Subject
实例:
1、定义一个Weather实体类
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 + '\'' +
'}';
}
}
2、定义观察者
我们想要这个被观察者能够通用,将其定义成泛型。内部应该暴露register和unregister方法供观察者订阅和取消订阅,至于观察者的保存,直接用ArrayList即可,此外,当有主题内容发送改变时,会即时通知观察者做出反应,因此应该暴露一个notifyObservers方法,以上方法的具体实现见如下代码。
import java.util.ArrayList;
import java.util.List;
public class Observable {
List> mObservers = new ArrayList>();
public void register(Observer observer){
if (observer == null){
throw new NullPointerException("observer == null");
}
synchronized (this){
if(!mObservers.contains(observer)){
mObservers.add(observer);
}
}
}
public synchronized void unregister(Observer observer){
mObservers.remove(observer);
}
public void notifyObserver(T data){
for (Observer observer:mObservers) {
observer.onUpdate( this,data);
}
}
}
3、我们的观察者,只需要实现一个观察者的接口Observer,该接口也是泛型的。其定义如下
public interface Observer {
void onUpdate(Observable observable,T data);
}
一旦订阅的主题发送变换就会回调该接口。
我们来使用一下,我们定义了一个天气变换的主题,也就是被观察者,还有两个观察者观察天气变换,一旦变换了,就打印出天气信息,注意一定要调用被观察者的register进行注册,否则会收不到变换信息。而一旦不敢兴趣了,直接调用unregister方法进行取消注册即可
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
Observer observer1 = new Observer() {
@Override
public void onUpdate(Observable observable, Weather data) {
System.out.println("观察者1 :" +data.toString());
}
};
Observer observer2 = new Observer() {
@Override
public void onUpdate(Observable observable, Weather data) {
System.out.println("观察者2 :" +data.toString());
}
};
observable.register(observer1);
observable.register(observer2);
Weather weather=new Weather("晴转多云");
observable.notifyObserver(weather);
Weather weather1=new Weather("多云转阴");
observable.notifyObserver(weather1);
observable.unregister(observer1);
Weather weather2=new Weather("台风");
observable.notifyObserver(weather2);
}
}
输出结果:
EventBus中的观察者模式:观察者模式的三个典型方法它都具有,即注册,取消注册,发送事件
EventBus.getDefault().register(Object subscriber);
EventBus.getDefault().unregister(Object subscriber);
EventBus.getDefault().post(Object event);
RxJava
创建一个被观察者
Observable myObservable = Observable.create(
new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted();
}
}
);
创建一个观察者,也就是订阅者
Subscriber mySubscriber = new Subscriber() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
};
观察者进行事件的订阅
myObservable.subscribe(mySubscriber);
以上既为观察者模式的简介,详解见链接:
https://wenku.baidu.com/view/662028d0360cba1aa811da52.html?st=1
观察者模式在Android中被应用的很是频繁,包括一些优秀的开源框架都会用到,下篇我们开始学习一些Android中常用的一些开源框架,学习下其中的核心思想,看懂别人的代码到运用别人的代码,再到优化别人的代码,这段路程还很长,还需要很多的努力。
待续...