Java設(shè)計模式之觀察者模式原理與用法詳解
本文實例講述了Java設(shè)計模式之觀察者模式原理與用法。分享給大家供大家參考,具體如下:
什么是觀察者模式
可以這么理解:
觀察者模式定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。
這個主題對象在狀態(tài)上發(fā)生變化時,會通知所有觀察者對象,讓它們能夠自動更新自己。
也可以這樣理解:
觀察者模式是關(guān)于多個對象想知道一個對象中數(shù)據(jù)變化情況的一種成熟模式。觀察者模式中有一個稱作“主題”的對象和若干個稱作“觀察者”的對象,“主題”和“觀察者”之間是一種一對多的依賴關(guān)系。
當“主題”的狀態(tài)發(fā)生變化時,所有“觀察者”都得到通知。
日常生活中,最容易理解的例子就是微信公眾號。我們用微信訂閱的微信公共號就是這里所說的主題,而我們 每一個關(guān)注這個微信號的人就是這里的觀察者。公眾號每天有更新,所有訂閱者都會收到。
觀察者模式類圖:

應用場景
一般被用來實現(xiàn)事件處理系統(tǒng)。
觀察者模式組成
從定義看,可以分成兩個角色, 觀察者和被觀察對象(即主題)
從類圖看,代碼實現(xiàn)有四個角色:
-
抽象主題角色: 把所有對觀察者對象的引用保存在一個集合中,每個抽象主題角色都可以有任意數(shù)量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實現(xiàn)。
-
抽象觀察者角色:為所有具體的觀察者定義一個接口,在得到主題的通知時更新自己。
-
具體主題角色:在具體主題內(nèi)部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。具體主題角色通常用一個子類實現(xiàn)。
-
具體觀察者角色:該角色實現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài)相協(xié)調(diào)。通常用一個子類實現(xiàn)。如果需要,具體觀察者角色可以保存一個指向具體主題角色的引用。
代碼實現(xiàn)觀察者模式
- 抽象主題角色
主題接口規(guī)定了具體主題需要實現(xiàn)的添加,刪除及通知觀察者更新數(shù)據(jù)的方法
/**
* 抽象主題,被觀察者
*
*/
public interface Subject {
/**
* 添加觀察者
*
* @param observer
*/
void addObserver(Observer observer);
/**
* 移除指定的觀察者
*
* @param observer
*/
void removeObserver(Observer observer);
/**
* 移除所有的觀察者
*/
void removeAll();
/**
* data 是要通知給觀察者的數(shù)據(jù) 因為Object是所有類的父類,可以使用多態(tài),當然 你也可以使用 泛型
*
* @param data
*/
void notifyAllObserver(Object data);
/**
* 單獨 通知某一個觀察者
*
* @param observer
* @param data
* data 是要通知給觀察者的數(shù)據(jù) 因為Object是所有類的父類,可以使用多態(tài),當然 你也可以使用 泛型
*/
void notify(Observer observer, Object data);
}
- 抽象觀察者角色
觀察者接口規(guī)定了具體觀察者用來更新數(shù)據(jù)的方法
/**
* 抽象觀察者接口
*/
public interface Observer {
/**
*
* @param subject 被觀察者
* @param data 被觀察者傳遞給觀察者的 數(shù)據(jù)
*/
void update(Subject subject,Object data);
}
- 具體主題角色
public class ConcreteSubject implements Subject {
//觀察者集合,用于管理所有的觀察者
List<Observer> mList = new ArrayList<>();
@Override
public void addObserver(Observer observer) {
// TODO Auto-generated method stub
// 確保相同的觀察者只含有一個
if (observer == null) {
throw new NullPointerException("observer == null");
}
if (!mList.contains(observer)) {
mList.add(observer);
}
}
@Override
public void removeObserver(Observer observer) {
// TODO Auto-generated method stub
mList.remove(observer);
}
@Override
public void removeAll() {
// TODO Auto-generated method stub
mList.clear();
}
@Override
public void notifyAllObserver(Object data) {
// TODO Auto-generated method stub
for (Observer observer : mList) {
observer.update(this, data);
}
}
@Override
public void notify(Observer observer, Object data) {
// TODO Auto-generated method stub
if (observer != null) {
observer.update(this, data);
}
}
}
- 具體的觀察者角色
這里我們可以定義多個具體的觀察者角色
觀察者One
public class ObserverOne implements Observer {
@Override
public void update(Subject subject, Object data) {
// TODO Auto-generated method stub
System.err
.println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());
}
}
觀察者Two
public class ObserverTwo implements Observer {
@Override
public void update(Subject subject, Object data) {
// TODO Auto-generated method stub
System.err
.println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());
}
}
觀察者Three
public class ObserverThree implements Observer {
@Override
public void update(Subject subject, Object data) {
// TODO Auto-generated method stub
System.err
.println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());
}
}
- 測試類
public class TestObservePattern {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConcreteSubject concreteSubject = new ConcreteSubject();
ObserverOne observerOne=new ObserverOne();
ObserverTwo observerTwo=new ObserverTwo();
ObserverThree observerThree=new ObserverThree();
concreteSubject.addObserver(observerOne);
concreteSubject.addObserver(observerTwo);
concreteSubject.addObserver(observerThree);
//通知所有的觀察者
concreteSubject.notifyAllObserver("wake up,wake up");
//通知某個特定的觀察者OberverTwo
concreteSubject.notify(observerTwo, "Specila msg for you");
//觀察者ObserveThree 決定不再訂閱主題
concreteSubject.removeObserver(observerThree);
//通知所有的觀察者
concreteSubject.notifyAllObserver("new Message come ");
}
}
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
SpringMvc向request域中設(shè)置數(shù)據(jù)的方法
這篇文章主要介紹了SpringMvc向request域中設(shè)置數(shù)據(jù)的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
java連接zookeeper實現(xiàn)zookeeper教程
這篇文章主要介紹了java連接zookeeper實現(xiàn)zookeeper教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
springboot+HttpInvoke?實現(xiàn)RPC調(diào)用的方法
RPC框架大家或多或少都用過,出自于阿里系的就有dubbo,HSF,sofaRPC等,今天通過本文給大家介紹springboot+HttpInvoke?實現(xiàn)RPC調(diào)用的方法,感興趣的朋友一起看看吧2022-03-03

