定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
设计原则
- 为了交互对象之间的松耦合设计而努力。
常见实例
- 监听器
简单例子
1、自定接口实现。
1、subject主题(被观察者)接口,代码如下:
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyAllObservers(String content);
}
2、observer观察者接口,代码如下:
public interface Observer {
void receive(String string);
}
3、subject接口实现,暴走大TV:
public class BaoZouBigTV implements Subject {
/**
* 订阅者的列表
*/
private ArrayList<Observer> observerArrayList;
BaoZouBigTV() {
this.observerArrayList = new ArrayList<>();
}
@Override
public void addObserver(Observer observer) {
observerArrayList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int i = observerArrayList.indexOf(observer);
if (i >= 0) {
observerArrayList.remove(i);
}
}
@Override
public void notifyAllObservers(String content) {
for (Observer observer : observerArrayList) {
observer.receive(content);
}
}
/**
* 增加一个暴走大事件,需要通知所有订阅者
*
* @param content
*/
public void addBaoZouThing(String content) {
notifyAllObservers(content);
}
}
分析:
(1)拥有一个Observer的列表。
(2)实现接口。
(3)完成自己的方法,增加了暴走事件,通知所有订阅者。
4、观察者实现,用户订阅暴走大TV:
public class Shen implements Observer {
@Override
public void receive(String string) {
System.out.println("Shen收到:" + string);
}
}
分析:实现了receive即可。
Demo分析:
(1)用户实现了Observer的接口,统一拥有receive的方法实现,在Subject中用Observer接口接收参数,参数一定有receive的方法;
(2)通知所有人时,调用ObserverArrayList中每个Observer的receive方法即可通知到所有人。
2、JAVA API实现
1、上面的subject(可/被观察者)对应于:java.util.Observable,它是一个类,我们需要让自己的类继承它。
import java.util.Observable;
public class BaoZouBigTV extends Observable {
/**
* 增加一个暴走大事件,需要通知所有订阅者
*
* @param content
*/
public void addBaoZouThing(String content) {
setChanged();
notifyObservers(content);
}
}
与我们自己设计的不同的是:继承于API实现的Observable类中的方法,有一个setChanged
方法,这个方法用于推送,必须调用该方法,我们去调用notifyObservers时才可以成功推送到观察者。
深入源码,我们可以看到这里的逻辑很好理解:
Observable有两个通知方法,一个是notifyObservers(),一个是notifyObservers(Object arg),第一个不带参数的方法实际调用了notifyObservers(null)方法。
2、java.util包下还有一个java.util.Observer
,对应于我们自己写的接口Observer。
import java.util.Observable;
import java.util.Observer;
public class Shen implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("Shen收到:" + arg);
}
}
其中覆写的方法update中有两个参数,一个是可观察对象o
,它可以让观察者去拉取(get)
“可观察者”的某些数据;一个是传进来的参数Object,用于接收可观察对象主动推送
的信息。
3、测试。
public class Test {
public static void main(String args[]) {
BaoZouBigTV baoZouBigTV = new BaoZouBigTV();
Shen shen = new Shen();
Hong hong = new Hong();
Bin bin = new Bin();
baoZouBigTV.addObserver(shen);
baoZouBigTV.addObserver(hong);
baoZouBigTV.addObserver(bin);
baoZouBigTV.addBaoZouThing("暴走大事件3");
}
}
输出:
我们会发现:观察者的调用和我们的绑定顺序不同,这点是正常的,我们不能把一些逻辑设计依赖于这个调用顺序。