Java設(shè)計模式之觀察者模式(Observer模式)
一、觀察者模式是什么?
當對象間存在一對多關(guān)系時,則使用觀察者模式(Observer Pattern)。當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
人話: 就像微信公眾號推送消息,訂閱的人能收到,沒訂閱的收不到,還可以取消/添加訂閱
二、模式分析
2.1 四個角色
- 抽象主題(抽象被觀察者角色):也就是一個抽象主題,它把所有對觀察者對象的引用保存在一個集合中,每個主題都可以有任意數(shù)量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實現(xiàn)。
- 抽象觀察者角色:為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
- 具體主題(具體被觀察者角色):也就是一個具體的主題,在集體主題的內(nèi)部狀態(tài)改變時,所有登記過的觀察者發(fā)出通知。
- 具體觀察者角色:實現(xiàn)抽象觀察者角色所需要的更新接口,一邊使本身的狀態(tài)與制圖的狀態(tài)相協(xié)調(diào)。
2.2 案例
- 微信公眾號
1.抽象主題
public interface Subject { /** * 注冊觀察者 */ void registerObserver(observer observer); /** * 移除觀察者 */ void removeObserver(observer observer); /** * 通知觀察者 */ void notifyObservers(); }
2.抽象觀察者角色
public interface observer { /** * 更新 */ void update(String message); }
3.具體主題
用Vector是線程同步的,比較安全,也可以使用ArrayList,是線程異步的,但不安全。
public class WechatServer implements Subject{ //注意到這個List集合的泛型參數(shù)為Observer接口,設(shè)計原則:面向接口編程而不是面向?qū)崿F(xiàn)編程 private Vector<observer> list; private String message; public WechatServer() { list = new Vector<observer>(); } @Override public void registerObserver(observer observer) { list.add(observer); } @Override public void removeObserver(observer observer) { if(!list.isEmpty()) list.remove(observer); } @Override public void notifyObservers() { for(int i = 0; i < list.size(); i++) { observer oserver = list.get(i); oserver.update(message); } } public void setInfomation(String s) { this.message = s; System.out.println("微信服務(wù)更新消息: " + s); //消息更新,通知所有觀察者 notifyObservers(); } }
4.具體觀察者角色
public class User implements observer { private String name; private String message; public User(String name) { this.name = name; } @Override public void update(String message) { this.message = message; read(); } public void read() { System.out.println(name + " 收到推送消息: " + message); } }
5.測試類
public class Test { public static void main(String[] args) { //主題 WechatServer server = new WechatServer(); //觀察者 observer userZhang = new User("ZhangSan"); observer userLi = new User("LiSi"); observer userWang = new User("WangWu"); server.registerObserver(userZhang); server.setInfomation("C是世界上最好用的語言!"); System.out.println("===================================="); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("JAVA是世界上最好用的語言!"); } }
6.結(jié)果
三、觀察者模式的優(yōu)缺點
優(yōu)點
解除耦合,讓耦合的雙方都依賴于抽象,從而使得各自的變換都不會影響另一邊的變換。
缺點
在應(yīng)用觀察者模式時需要考慮一下開發(fā)效率和運行效率的問題,程序中包括一個被觀察者、多個觀察者,開發(fā)、調(diào)試等內(nèi)容會比較復(fù)雜,而且在Java中消息的通知一般是順序執(zhí)行,那么一個觀察者卡頓,會影響整體的執(zhí)行效率,在這種情況下,一般會采用異步實現(xiàn)。
四、總結(jié)
當一個對象的改變需要同時改變其它對象,并且它不知道具體有多少對象有待改變的時候,應(yīng)該考慮使用觀察者模式。 而使用觀察者模式的動機在于:將一個系統(tǒng)分割成一系列相互協(xié)作的類有一個很不好的副作用,就是需要維護相關(guān)對象間的一致性,我們不希望為了維持一致性而使各類緊密耦合,這樣會給維護、擴展和重用都帶來不便,而觀察者模式所做的工作就是在解除耦合。
到此這篇關(guān)于Java設(shè)計模式之觀察者模式(Observer模式)的文章就介紹到這了,更多相關(guān)Java觀察者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA初級項目——實現(xiàn)圖書管理系統(tǒng)
這篇文章主要介紹了JAVA如何實現(xiàn)圖書管理系統(tǒng),文中示例代碼非常詳細,供大家參考和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06Spring依賴注入中的@Resource與@Autowired詳解
這篇文章主要介紹了Spring依賴注入中的@Resource與@Autowired詳解,提到Spring依賴注入,大家最先想到應(yīng)該是@Resource和@Autowired,對于Spring為什么要支持兩個這么類似的注解卻未提到,屬于知其然而不知其所以然,本文就來做詳細講解,需要的朋友可以參考下2023-09-09關(guān)于Java錯誤提示之找不到或無法加載主類的問題及正確處理方法
當我們在初學(xué)Java的是時候,類文件中是不設(shè)定包名(package)的,這種情況下注意classpath,基本上沒有問題,?本文主要說明classpath和系統(tǒng)環(huán)境變量PATH都沒問題的情況下出錯原因和正確處理方法,感興趣的朋友一起看看吧2022-01-01java反射機制的一些學(xué)習(xí)心得小結(jié)
這篇文章主要給大家介紹了關(guān)于java反射機制的一些學(xué)習(xí)心得,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02Java基礎(chǔ)知識之BufferedReader流的使用
這篇文章主要介紹了Java基礎(chǔ)知識之BufferedReader流的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Java壓縮解壓zip技術(shù)_動力節(jié)點Java學(xué)院整理
Java解壓縮zip - 多個文件(包括文件夾),對多個文件和文件夾進行壓縮,對復(fù)雜的文件目錄進行解壓。壓縮方法使用的是可變參數(shù),可以壓縮1到多個文件2017-05-05