定義
觀察者模式定義了對(duì)象間一對(duì)多的依賴(lài)關(guān)系,使得對(duì)象狀態(tài)發(fā)生變化時(shí)秕磷,所有依賴(lài)它的對(duì)象都會(huì)受到通知并且自動(dòng)更新自己。通俗來(lái)說(shuō)就是多個(gè)觀察者訂閱了一個(gè)被觀察者的時(shí)候,被觀察者發(fā)生改變時(shí)引镊,會(huì)自動(dòng)通知觀察者,而不需要觀察者去詢(xún)問(wèn)被觀察者是否發(fā)生改變。
觀察者模式中的角色組成
- 抽象被觀察者角色:定義了添加弟头,刪除和通知觀察者的方法吩抓。
- 具體被觀察者角色:繼承抽象被觀察者的抽象類(lèi),實(shí)現(xiàn)自身的業(yè)務(wù)邏輯赴恨,當(dāng)狀態(tài)發(fā)生改變時(shí)疹娶,發(fā)起通知。
- 抽象觀察者角色:提供一個(gè)接口伦连,定義了觀察者收到通知時(shí)更新自己的方法雨饺。
- 具有觀察者角色:實(shí)現(xiàn)抽象觀察者接口,處理不同具體觀察者的不同業(yè)務(wù)邏輯惑淳。
實(shí)例
現(xiàn)在有一個(gè)讀書(shū)平臺(tái)额港,有很多個(gè)讀者訂閱了一個(gè)作者的說(shuō),但是這個(gè)作者更新時(shí)間是不一定的歧焦,讀者們都想第一去讀到最新的章節(jié)移斩,但是讀者又不能時(shí)刻去關(guān)注作者是否已經(jīng)更新,因此很多讀者要求作者在更新小說(shuō)的時(shí)候绢馍。并且當(dāng)讀者不想訂閱的時(shí)候向瓷,可以取消訂閱。這個(gè)時(shí)候我們就可以使用觀察者模式解決這個(gè)問(wèn)題舰涌。
被觀察者的抽象類(lèi):
這個(gè)類(lèi)是抽象類(lèi)猖任,是所有被觀察者都要求繼承的,其中提供了添加瓷耙,刪觀察者超升,支持只通知個(gè)別的觀察者,或者所有的觀察者的功能哺徊。
/**
* 被觀察者的抽象類(lèi)
*
*/
abstract class Subject{
private List<Observer> observers=new ArrayList<Observer>();
/**
* 訂閱的方法
* @param observer
*/
public void subscribe(Observer observer) {
if (observer!=null) {
if (!observers.contains(observer)) {
observers.add(observer);
System.out.println(observer.getObserverName()+"訂閱了");
}
}
}
/**
* 取消訂閱
*/
public void unSubscribe(Observer observer) {
if (observers.contains(observer)) {
observers.remove(observer);
System.out.println(observer.getObserverName()+"取消訂閱了");
}
}
/**
* 通知一個(gè)觀察者
* @param observer
*/
public void notifyObserver(Observer observer) {
if (observer!=null) {
observer.update(" 已經(jīng)更新: "+notifyUpadteContext());
}
}
/**
* 通知所有的觀察者
*
*/
public void notifyAllObserver() {
for(Observer observer:observers) {
notifyObserver(observer);
}
}
/**
* 子類(lèi)要實(shí)現(xiàn)的更新小說(shuō)的方法室琢,返回更新的內(nèi)容
* @return
*/
public abstract String notifyUpadteContext();
}
被觀察者的實(shí)現(xiàn)類(lèi)
被觀察者的實(shí)現(xiàn)類(lèi),在這個(gè)案例當(dāng)中落追,小說(shuō)作者就是被觀察者盈滴,發(fā)布更新的消息,并通知觀察者轿钠。
/**
* 小說(shuō)作者巢钓,即是被觀察者
*
*/
class WriterSubject extends Subject{
private String mUpdateContext;
public void write(String context) {
mUpdateContext=context;
//通知更新所有的觀察者
notifyAllObserver();
}
public void write(String context,Observer observer) {
mUpdateContext=context;
//通知更新個(gè)別的觀察者
notifyObserver(observer);
}
/**
* 返回更新的內(nèi)容,只有父類(lèi)去調(diào)用獲得的內(nèi)容通知觀察者
*/
@Override
public String notifyUpadteContext() {
return mUpdateContext;
}
}
觀察者的接口
觀察者的接口疗垛,最重要的方法是收到被觀察者的更新消息之后去做相關(guān)的邏輯處理症汹。
/**
* 觀察者的接口
*
*/
interface Observer{
/**
* 返回觀察者的名稱(chēng)
* @return
*/
String getObserverName();
/**
* 進(jìn)行更新的操作
* @param message
*/
void update(String message);
}
具體的觀察者
具體的觀察者,等到更新的做出具體的處理贷腕。
class XiaoMing implements Observer{
@Override
public String getObserverName() {
return "小明";
}
@Override
public void update(String message) {
System.out.println("小明收到小說(shuō)更新的通知:"+message);
}
}
class XiaoHong implements Observer{
@Override
public String getObserverName() {
return "小紅";
}
@Override
public void update(String message) {
System.out.println("小紅收到小說(shuō)更新的通知:"+message);
}
}
class XiaoBai implements Observer{
@Override
public String getObserverName() {
return "小白";
}
@Override
public void update(String message) {
System.out.println("小白收到小說(shuō)更新的通知:"+message);
}
}
調(diào)用代碼:
public static void main(String[] args) {
WriterSubject writerSubject=new WriterSubject();
XiaoMing xiaoMing=new XiaoMing();
XiaoHong xiaoHong=new XiaoHong();
XiaoBai xiaoBai=new XiaoBai();
writerSubject.subscribe(xiaoMing);
writerSubject.subscribe(xiaoBai);
writerSubject.subscribe(xiaoHong);
writerSubject.write("第10章");
writerSubject.write("第11章",xiaoMing);
writerSubject.unSubscribe(xiaoBai);
writerSubject.write("第12章");
}
結(jié)果:
從結(jié)果可以看到當(dāng)被觀察者更新了小說(shuō)之后背镇,訂閱的觀察者們將會(huì)作出相應(yīng)的處理咬展,觀察者模式在我看來(lái)的核心就是Android開(kāi)發(fā)中用到的接口回調(diào)的思路。