觀(guān)察者模式也被稱(chēng)為發(fā)布-訂閱(Publish/Subscribe)模式,它屬于行為型模式的一種。觀(guān)察者模式定義了一種一對(duì)多的依賴(lài)關(guān)系,一個(gè)主題對(duì)象可被多個(gè)觀(guān)察者對(duì)象同時(shí)監(jiān)聽(tīng)。當(dāng)這個(gè)主題對(duì)象狀態(tài)變化時(shí),會(huì)通知所有觀(guān)察者對(duì)象并作出相應(yīng)處理邏輯。
模型圖

觀(guān)察者模式定義了四種角色:抽象主題、具體主題、抽象觀(guān)察者、具體觀(guān)察者。
抽象主題(Subject):該角色是一個(gè)抽象類(lèi)或接口,定義了增加、刪除、通知觀(guān)察者對(duì)象的方法。
具體主題(ConcreteSubject):該角色繼承或?qū)崿F(xiàn)了抽象主題,定義了一個(gè)集合存入注冊(cè)過(guò)的具體觀(guān)察者對(duì)象,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時(shí),給所有注冊(cè)過(guò)的觀(guān)察者發(fā)送通知。
抽象觀(guān)察者(Observer):該角色是具體觀(guān)察者的抽象類(lèi),定義了一個(gè)更新方法。
具體觀(guān)察者(ConcrereObserver):該角色是具體的觀(guān)察者對(duì)象,在得到具體主題更改通知時(shí)更新自身的狀態(tài)。
實(shí)現(xiàn)代碼
抽象觀(guān)察者(Observer)接口
public interface Observer{
public void update(string msg);
}
具體觀(guān)察者(ConcreteObserver)類(lèi)
public class ConcreteObserver implement Observer{
private mName = name;
public ConcreteObserver(String name){
mName = name;
}
public void update(string msg){
Toast.makeToast(this, mName + msg, 0).show();
}
}
抽象主題(Subject)接口
public class Subject{
public void register(Observer observer);
public void unregister(Observer observer);
public void notifyAll(string msg);
}
具體主題(ConcreteSubject)類(lèi)
public class ConcreteSubject implement Subject{
ArrayList<Observer> observers;
public Subject(){
observers = new ArrayList<Observer>();
}
@Override
public void register(Observer observer){
observers.add(observer);
}
@Override
public void unregister(Observer observer){
observers.remove(observer);
}
@Override
public void notifyAll(string msg){
for (Observer observer : observers ) {
observer.update(msg);
}
public void notifyDataChange(String newMsg){
notifyAll(newMsg);
}
}
MainActivity類(lèi)
public class MainActivity extends Activity{
public void onCreate(Bundle savedInstanceState){
ConcreteSubject subject = new ConcreteSubject();
subject.register(new ConcreteObserver("test1");
subject.register(new ConcreteObserver("test2");
Button btn = findviewbyId(R.id.test);
btn.setOnclickListener(new OnClickListener{
@Override
public void onClick(View view){
subject.notifyDataChange("我變了,請(qǐng)注意查收");
}
}
}
優(yōu)點(diǎn)
1.觀(guān)察者模式符合松耦合
通過(guò)一個(gè)列表來(lái)維護(hù)觀(guān)察者,這使得被觀(guān)察者無(wú)需在意觀(guān)察者的具體類(lèi)型,只需要發(fā)送消息進(jìn)行通知即可,通過(guò)調(diào)用update方法,觀(guān)察者也無(wú)須關(guān)系被觀(guān)察者的情況,只當(dāng)有狀態(tài)改變時(shí)進(jìn)行更新即可。觀(guān)察者增加或刪除無(wú)需修改主題的代碼,只需調(diào)用主題對(duì)應(yīng)的增加或者刪除的方法即可。
2.觀(guān)察者不會(huì)因主動(dòng)獲取通知而錯(cuò)過(guò)狀態(tài)
由于被動(dòng)接受,正常情況下不會(huì)錯(cuò)過(guò)主題的改變通知。而主動(dòng)獲取的話(huà),由于時(shí)機(jī)選取問(wèn)題,可能導(dǎo)致錯(cuò)過(guò)某些狀態(tài)。
3.表示層和數(shù)據(jù)邏輯層的分離
觀(guān)察者模式可以實(shí)現(xiàn)表示層和數(shù)據(jù)邏輯層的分離,并定義了穩(wěn)定的消息更新傳遞機(jī)制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀(guān)察者角色。觀(guān)察者模式在觀(guān)察目標(biāo)和觀(guān)察者之間建立一個(gè)抽象的耦合。觀(guān)察者模式支持廣播通信。觀(guān)察者模式符合“開(kāi)閉原則”的要求。
缺點(diǎn)
1.如果一個(gè)被觀(guān)察者對(duì)象有很多的直接和間接的觀(guān)察者的話(huà),將所有的觀(guān)察者都通知到會(huì)花費(fèi)很多時(shí)間
2.雖然觀(guān)察者模式可以隨時(shí)使觀(guān)察者知道所觀(guān)察的對(duì)象發(fā)生了變化,但是觀(guān)察者模式?jīng)]有相應(yīng)的機(jī)制使觀(guān)察者知道所觀(guān)察的對(duì)象是怎么發(fā)生變化的
應(yīng)用場(chǎng)景:
1、 對(duì)一個(gè)對(duì)象狀態(tài)的更新,需要其他對(duì)象同步更新,而且其他對(duì)象的數(shù)量動(dòng)態(tài)可變。
2、 對(duì)象僅需要將自己的更新通知給其他對(duì)象而不需要知道其他對(duì)象的細(xì)節(jié)。