前言
觀察者模式是我們使用率比較高的一種模式了涧狮。這類(lèi)文章網(wǎng)上也不少这嚣,通過(guò)本文我會(huì)讓你徹底理解并記住什么事觀察者模式。觀察者模式使用率之所以比較高,是因?yàn)樗贏ndroid中能達(dá)到一個(gè)十分明顯的解耦效果。讓觀察者和被觀察者邏輯分開(kāi)浪默。使得UI層和業(yè)務(wù)邏輯清晰。更加利于我們拓展代碼缀匕。
觀察者模式定義
定義一個(gè)被觀察者和多個(gè)觀察者纳决,每當(dāng)被觀察者變化,所有觀察者都會(huì)得到通知乡小。
理解重點(diǎn)
觀察者模式核心就一個(gè)點(diǎn)阔加,記住這個(gè)點(diǎn)你就能理解并記憶。要點(diǎn):用一個(gè)list把觀察者保存起來(lái)满钟,并提供add和remove觀察者胜榔,在被觀察者變化的時(shí)候就遍歷并調(diào)用list里觀察者的方法。核心就是一個(gè)list遍歷
下面我將用兩個(gè)例子來(lái)具體說(shuō)明觀察者模式湃番。例一是JDK自帶的接口夭织,例二是自己寫(xiě)觀察者模式
例子一
先來(lái)一個(gè)訂閱發(fā)布的例子。我們定義Android發(fā)布新的版本吠撮。Android為被觀察者尊惰,當(dāng)新版本發(fā)布的時(shí)候,我們通知所有觀察者泥兰,新版本已發(fā)布弄屡。
1、定義觀察者
public class PersonObserver implements Observer {
static final String TAG = PersonObserver.class.getSimpleName();
String name;
public PersonObserver (String name) {
this.name = name;
}
@Override
public void update(Observable observable, Object o) {
Log.d(TAG,name + " 接收到通知啦 "+ o);
}
}
觀察者就實(shí)現(xiàn)一個(gè)接口update方法鞋诗,當(dāng)被觀察者發(fā)送消息的時(shí)候膀捷,我們就在update里接收
2、定義被觀察者
public class AndroidObervable extends Observable {
static final String TAG = AndroidObervable.class.getSimpleName();
public void postNewVersion(String version) {
setChanged(); // 標(biāo)示內(nèi)容發(fā)生改變
notifyObservers(version);// 通知所有觀察者
}
}
被觀察者繼承自O(shè)bservable师脂,Observable里已經(jīng)定義好了list,add,delete等方法担孔,很好理解。
3吃警、最后我們來(lái)看下怎么用的
PersonObserver xiaoMing = new PersonObserver("xiaoMing");
PersonObserver xiaoDong = new PersonObserver("xiaoDong");
PersonObserver xiaoHong = new PersonObserver("xiaoHong");
// 添加到集合里糕篇。
AndroidObervable android = new AndroidObervable();
android.addObserver(xiaoMing);
android.addObserver(xiaoDong);
android.addObserver(xiaoHong);
// 通知
android.postNewVersion("android O updated!");
android.postNewVersion("android P updated!");
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoMing 接收到通知啦 android O updated!
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoDong 接收到通知啦 android O updated!
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoHong 接收到通知啦 android O updated!
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoMing 接收到通知啦 android P updated!
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoDong 接收到通知啦 android P updated!
11-20 10:05:57.004 13623-13623/com.yink.designpattern.designpattern D/PersonObserver: xiaoHong 接收到通知啦 android P updated!
看輸出都通知到了。觀察者模式采用JDK原生的方式實(shí)現(xiàn)起來(lái)很簡(jiǎn)單酌心。JDK都給我們封裝好了拌消。只管添加就好。這個(gè)例子適合我們先對(duì)觀察者模式有一個(gè)大概理解,知道這就是觀察者模式墩崩。
例二
接下來(lái)我們自己來(lái)實(shí)現(xiàn)觀察者模式氓英。我們以觀察天氣變化為例。
1鹦筹、定義觀察者
public abstract class WeatherOberver {
public void typhoon() {
}
public abstract void sun();
public abstract void rain();
}
這里和例一的差別是铝阐,我們用的抽象類(lèi),沒(méi)用接口铐拐,他們思想都相似徘键。這里我是為了區(qū)分事件吹害,我們也可以用接口寫(xiě),然后把各種天氣用一個(gè)變量表示,這里就不詳述了。
2、定義被觀察者
public class WeatherObervable extends WeatherOberver{
ArrayList<WeatherOberver> list = new ArrayList<>();
public void add(WeatherOberver observerListener) {
list.add(observerListener);
}
public void remove(WeatherOberver observerListener) {
if (list.contains(observerListener)){
list.remove(observerListener);
}
}
@Override
public void typhoon() {
for (WeatherOberver observerListener : list) {
observerListener.typhoon();
}
}
@Override
public void sun() {
for (WeatherOberver observerListener : list) {
observerListener.sun();
}
}
@Override
public void rain() {
for (WeatherOberver observerListener : list) {
observerListener.rain();
}
}
}
被觀察者的實(shí)現(xiàn)也是簡(jiǎn)單粗暴搂妻。這里就體現(xiàn)了我們文章開(kāi)始的時(shí)候說(shuō)的觀察者模式的核心了邓厕。一個(gè)list提供add,remove方法呵哨,把觀察者放到集合里敞掘。需要通知的時(shí)候遍歷通知即可。這下就好理解了吧。
3哭廉、最后看看調(diào)用。
private WeatherOberver xiaoDong = new WeatherOberver() {
@Override
public void typhoon() {
Log.d("xiaoDong","吹臺(tái)風(fēng),要放假了加酵。哈哈!");
}
@Override
public void sun() {
}
@Override
public void rain() {
Log.d("xiaoDong","下雨了哭当,帶傘");
}
};
private WeatherOberver xiaoMing = new WeatherOberver() {
@Override
public void sun() {
}
@Override
public void rain() {
Log.d("xiaoMing","下雨了猪腕,帶傘");
}
};
WeatherObervable weatherObervable = new WeatherObervable();
weatherObervable.add(xiaoMing);
weatherObervable.add(xiaoDong);
weatherObervable.rain();
weatherObervable.typhoon();
11-20 11:16:21.284 15580-15580/com.yink.designpattern.designpattern D/xiaoMing: 下雨了,帶傘
11-20 11:16:21.284 15580-15580/com.yink.designpattern.designpattern D/xiaoDong: 下雨了钦勘,帶傘
11-20 11:16:21.284 15580-15580/com.yink.designpattern.designpattern D/xiaoDong: 吹臺(tái)風(fēng)陋葡,要放假了。哈哈彻采!
因?yàn)橛^察者我用的抽象類(lèi)腐缤,除了天晴和下雨是必須繼承的方法,刮臺(tái)風(fēng)可繼承可不繼承肛响。所以我們可以更方便的觀察我們需要觀察的對(duì)象岭粤。小東在廣東,吹臺(tái)風(fēng)他們公司就放假终惑。所以他只關(guān)心哪天吹臺(tái)風(fēng)绍在。小明比較講究健康,關(guān)注下雨,下雨就帶傘偿渡。
觀察者模式小結(jié)
觀察者模式就是將觀察者和被觀察者徹底隔離臼寄,實(shí)現(xiàn)解耦,只依賴(lài)于我們定義的抽象溜宽。觀察者模式運(yùn)用十分廣泛吉拳,比如我們的ListView運(yùn)用了觀察者模式和Adapter是的Listview的可擴(kuò)展性,靈活性非常強(qiáng)适揉。還有比較出名的開(kāi)源庫(kù)EventBus也是用了觀察者模式的思想實(shí)現(xiàn)解耦留攒。
總結(jié)
優(yōu)點(diǎn):1、觀察者和被觀察者解耦 2嫉嘀、增強(qiáng)靈活性炼邀,解耦
缺點(diǎn):由于java代碼的順序執(zhí)行,要考慮被察者的執(zhí)行效率剪侮,多個(gè)觀察者需要及時(shí)響應(yīng)就得考慮異步的問(wèn)題了拭宁。
觀察模式核心:一個(gè)list合集,提供add,remove方法瓣俯,遍歷觀察者杰标,就是一個(gè)list的遍歷。