【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
生活随笔
收集整理的這篇文章主要介紹了
【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、觀察者模式簡介
- 二、觀察者模式適用場景
- 三、觀察者模式優缺點
- 四、觀察者模式代碼示例
- 1、被觀察者
- 2、觀察者
- 3、通知類
- 4、測試類
- 五、JDK 中的觀察者模式支持類
- 1、Observable
- 2、Observer
一、觀察者模式簡介
觀察者模式 : 定義了 對象之間 一對多 的 依賴 , 令 多個 觀察者 對象 同時 監聽 某一個 主題對象 , 當 主題對象 發生改變時 , 所有的 觀察者 都會 收到通知 并更新 ;
觀察者 有多個 , 被觀察的 主題對象 只有一個 ;
如 : 在購物網站 , 多個用戶關注某商品后 , 當商品降價時 , 就會自動通知關注該商品的用戶 ;
- 主題對象 : 商品是主題對象 ;
- 觀察者 : 用戶是觀察者 ;
- 觀察者注冊 : 用戶關注 , 相當于注冊觀察者 ;
- 通知觸發條件 : 商品降價 ;
觀察者模式 類型 : 行為型 ;
二、觀察者模式適用場景
觀察者模式適用場景 : 關聯行為 場景 , 建立一套 觸發機制 ;
如 : 用戶關注某個商品的價格 , 降價時進行通知 , 這樣 用戶 和 商品 產生了關聯 , 觸發機制就是 商品降價 ,
三、觀察者模式優缺點
觀察者模式 優點 :
- 抽象耦合 : 在 觀察者 和 被觀察者 之間 , 建立了一個 抽象的 耦合 ; 由于 耦合 是抽象的 , 可以很容易 擴展 觀察者 和 被觀察者 ;
- 廣播通信 : 觀察者模式 支持 廣播通信 , 類似于消息廣播 , 如果需要接收消息 , 只需要注冊一下即可 ;
觀察者模式 缺點 :
- 依賴過多 : 觀察者 之間 細節依賴 過多 , 會增加 時間消耗 和 程序的復雜程度 ;
這里的 細節依賴 指的是 觸發機制 , 觸發鏈條 ; 如果 觀察者設置過多 , 每次觸發都要花很長時間去處理通知 ; - 循環調用 : 避免 循環調用 , 觀察者 與 被觀察者 之間 絕對不允許循環依賴 , 否則會觸發 二者 之間的循環調用 , 導致系統崩潰 ;
四、觀察者模式代碼示例
JDK 中提供了觀察者模式的支持 ;
- 被觀察者 : 被觀察者 繼承 Observable 類 ;
- 觀察者 : 觀察者 實現 Observer 接口 ;
- 關聯 觀察者 與 被觀察者 : 調用 被觀察者 的 addObserver 方法 , 關聯二者 ;
- 觸發通知 : 被觀察者 數據改變時 , 調用 setChanged 和 notifyObservers 方法 , 會自動回調 觀察者的 update 方法 ;
用戶在游戲中提出問題 , 管理員負責監聽并處理問題 ;
1、被觀察者
package observer;import java.util.Observable;/*** 被觀察的主題對象* JDK 提供了對觀察者模式的支持 , 被觀察者可以繼承 Observable 類** 被觀察對象 繼承 Observable 類*/ public class Game extends Observable {private String name;public Game(String name) {this.name = name;}public String getName() {return name;}/*** 用戶提交問題* @param game* @param question*/public void produceQuestion(Game game, Question question) {System.out.println(question.getUserName() +" 在 " + game.name + " 游戲中提交問題 : " + question.getContent());// 該方法是 Observable 提供的方法// 將 private boolean changed = false 成員變量設置為 true// 代表 被觀察者 的狀態發生了改變setChanged();// 通知 觀察者notifyObservers(question);} }
2、觀察者
package observer;import java.util.Observable; import java.util.Observer;/*** 管理員類* 管理員類觀察的是游戲* 用戶反饋的問題 屬于 游戲 , 管理員關注的是游戲* 無法關注 問題** 如 : 在電商平臺 , 關注的是某個商品 , 在降價時發送通知* 商品是存在的 , 降價消息 在關注的時候還沒有被創建 , 是無法獲取依賴的*/ public class Manager implements Observer {/*** 管理員名稱*/private String name;public Manager(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {// 獲取 被觀察者 對象Game game = (Game) o;// 獲取 被觀察者 對象 調用 notifyObservers 方法的參數Question question = (Question) arg;System.out.println(name + " 觀察者 接收到 被觀察者 " + game.getName() +" 的通知 , 用戶 " + question.getUserName() +" 提出問題 " + question.getContent());} }
3、通知類
package observer;public class Question {/*** 用戶名*/private String userName;/*** 問題內容*/private String content;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getContent() {return content;}public void setContent(String content) {this.content = content;} }
4、測試類
package observer;public class Main {public static void main(String[] args) {// 創建被觀察者Game game = new Game("Cat And Mouse");// 創建觀察者Manager manager = new Manager("Tom");// 關聯 觀察者 與 被觀察者game.addObserver(manager);// 業務邏輯 : 用戶提出問題到游戲中 , 管理員接收到通知消息Question question = new Question();question.setUserName("Jerry");question.setContent("游戲崩潰");// 在游戲中提交問題game.produceQuestion(game, question);} }
執行結果 :
Jerry 在 Cat And Mouse 游戲中提交問題 : 游戲崩潰 Tom 觀察者 接收到 被觀察者 Cat And Mouse 的通知 , 用戶 Jerry 提出問題 游戲崩潰五、JDK 中的觀察者模式支持類
1、Observable
被觀察者需要繼承該類 ;
public class Observable {private boolean changed = false;/** 使用 Vector 是線程安全的集合 , 存放觀察者對象 , 在構造器中初始化該類 */private Vector<Observer> obs;/** Construct an Observable with zero Observers. */public Observable() {obs = new Vector<>();}/*** 添加觀察者對象 , 采用了 synchronized 修飾 , 是同步方法 , 保證了線程安全 ** @param o an observer to be added.* @throws NullPointerException if the parameter o is null.*/public synchronized void addObserver(Observer o) {if (o == null)throw new NullPointerException();if (!obs.contains(o)) {obs.addElement(o);}}/*** 刪除觀察者 */public synchronized void deleteObserver(Observer o) {obs.removeElement(o);}/*** 通知觀察者 , 無參** @see java.util.Observable#clearChanged()* @see java.util.Observable#hasChanged()* @see java.util.Observer#update(java.util.Observable, java.lang.Object)*/public void notifyObservers() {notifyObservers(null);}/*** 通知觀察者 , 有參** @param arg any object.* @see java.util.Observable#clearChanged()* @see java.util.Observable#hasChanged()* @see java.util.Observer#update(java.util.Observable, java.lang.Object)*/public void notifyObservers(Object arg) {Object[] arrLocal;synchronized (this) {if (!changed)return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}public synchronized void deleteObservers() {obs.removeAllElements();}protected synchronized void setChanged() {changed = true;}protected synchronized void clearChanged() {changed = false;}public synchronized boolean hasChanged() {return changed;}/*** 查看觀察者數量 ** @return the number of observers of this object.*/public synchronized int countObservers() {return obs.size();} }2、Observer
觀察者需要實現該接口 ;
package java.util;/*** A class can implement the <code>Observer</code> interface when it* wants to be informed of changes in observable objects.** @author Chris Warth* @see java.util.Observable* @since JDK1.0*/ public interface Observer {/*** 當 被觀察者 對象發生改變時 , 即被觀察者對象調用 notifyObservers 方法時 , 自動調用該方法** @param o 被觀察的對象.* @param arg 被觀察對象調用 notifyObservers 方法時傳入的參數 */void update(Observable o, Object arg); }總結
以上是生活随笔為你收集整理的【设计模式】观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【设计模式】备忘录模式 ( 简介 | 适
- 下一篇: 【设计模式】策略模式 ( 简介 | 适用