-
观察者模式是什么?
-
观察者模式的适用场景
-
观察者模式的使用方法
1. 举个栗子
当我们对同一组数据进行统计分析的时候,希望能够提供多种表示形式,例如表格、柱状图或者饼状图等。这些表示都依赖于同一组数据,当我们要对数据做出改变的时候,所有的统计的显示都将需要同时改变,也就是我们所说的,当“一”产生变化的时候,我们希望所有依赖这个“一”的“多”都能够发生同步改变。观察者(Observer)模式就是解决了这个问题。
2. 观察者模式是什么?
-
定义对象间的一种“一对多”的依赖关系,当一个对象(Observable)的状态发生改变时,所有依赖于它的对象(Observer)都会得到通知并被自动更新。(MVC就是观察者模式的一个实例)
-
观察者模式中主要有观察者(Observer)和被观察者(Observable)两个对象。
-
被观察者对象是一个抽象类,所以只能被继承。
-
观察者对象是一个接口,所以观察者可以有多个,实现了该接口的类都属于观察者。
-
一个对象既可以是观察者,又可以是被观察者。它可以继承Observable类,同时又可以实现Observer接口。
3. 观察者模式的适用场景
一个对象的状态更新了,需要其他对象同步更新,这个对象只需要将自己更新了这个消息通知给其他对象,而不需要知道其他对象的数量及其更新细节。
4. 观察者模式的使用方法
-
实例:被观察者为一个数字,有两个观察者,一个做加法,另一个做乘法,每次将被观察者进行加1的操作,两个观察者发生相应的变化。
-
被观察者MyObservable,继承Observable。
public class MyObservable extends Observable { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; setChanged();// 确认数据已经发生变化 notifyObservers();// 发送信号通知观察者 } }
-
观察者MyObserver,实现Observer接口。
public class MyObserver implements Observer { private MyObservable myObservable; public MyObservable getMyObservable() { return myObservable; } public void setMyObservable(MyObservable myObservable) { this.myObservable = myObservable; } @Override public void update(Observable o, Object arg) { this.myObservable = (MyObservable) o; } public int getObservableValue(){ if (EmptyUtils.isEmpty(getMyObservable())) return 0; if (EmptyUtils.isEmpty(getMyObservable().getContent())) return 0; return Integer.parseInt(getMyObservable().getContent()); } }
-
创建被观察者对象和两个观察者对象,被观察者通过addObserver()方法添加观察者对象observer1和observer2,然后改变被观察者的值,依次加1,观察者可以通过获取被观察者的值而分别发生相应的变化。实现方法如下:
public class ObserverMainActivity extends BaseActivity { @BindView(R.id.title_name_tv) TextView titleNameTv;// 标题 @BindView(R.id.observable_tv) TextView mObservableTv;// 被观察者 @BindView(R.id.observer_add_tv) TextView mObserverAddTv;// 观察者一,做加法 @BindView(R.id.observer_multip_tv) TextView mObserverMulTv;// 观察者二,做乘法 private int i = 1; private MyObservable myObservable; private MyObserver observer1; private MyObserver observer2; @Override protected int getLayoutResId() { return R.layout.activity_observer_main; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); titleNameTv.setText("观察者模式"); myObservable = new MyObservable(); observer1 = new MyObserver(); observer2 = new MyObserver(); myObservable.addObserver(observer1); myObservable.addObserver(observer2); myObservable.setContent(i + ""); notifyView(); } @OnClick(R.id.change_observable_btn) void onClick(View view) { i++; myObservable.setContent(i + ""); notifyView(); } /** * 刷新数据 */ private void notifyView() { mObservableTv.setText(myObservable.getContent()); mObserverAddTv.setText((observer1.getObservableValue() + observer1.getObservableValue()) + ""); mObserverMulTv.setText((observer2.getObservableValue() * observer2.getObservableValue()) + ""); } @Override protected void onDestroy() { super.onDestroy(); myObservable.deleteObservers(); } }
5. 观察者模式的优缺点
-
优点
(1) 观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者只知道一个具体的观察者列表,但并不认识任何一个具体的观察者,它只知道它们都有一个共同的接口,而每一个具体的观察者都会实现这样一个抽象接口。
(2) 观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知。
-
缺点
(1) 如果被观察者之间存在循环依赖的关系,那么将会导致系统崩溃;
(2) 如果对观察者的通知是通过另外的线程进行异步投递的话,那么系统必须保证投递是以自洽的方式进行的;
(3) 观察者只知道被观察者发生了变化,但是不知道被观察者是怎么发生变化的。