Java設(shè)計(jì)模式之觀察者模式
什么是觀察者模式
- 先講什么是行為性模型,行為型模式關(guān)注的是系統(tǒng)中對(duì)象之間的相互交互,解決系統(tǒng)在運(yùn)行時(shí)對(duì)象 之間的相互通信和協(xié)作,進(jìn)一步明確對(duì)象的職責(zé)。
- 觀察者模式,是一種行為性模型,又叫發(fā)布-訂閱模式,他定義對(duì)象之間一種一對(duì)多的依賴關(guān)系,使得當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并自動(dòng)更新。
觀察者模式職責(zé)
觀察者模式主要用于1對(duì)N的通知。當(dāng)一個(gè)對(duì)象的狀態(tài)變化時(shí),他需要及時(shí)告知一系列對(duì)象,令他們做出相應(yīng)。 實(shí)現(xiàn)有兩種方式:
- 推:每次都會(huì)把通知以廣播的方式發(fā)送給所有觀察者,所有的觀察者只能被動(dòng)接收。
- 拉:觀察者只要知道有情況即可,至于什么時(shí)候獲取內(nèi)容,獲取什么內(nèi)容,都可以自主決定。
應(yīng)用實(shí)例
現(xiàn)實(shí)中有一個(gè)金額變化以后,會(huì)有短信提示和支付寶提示的例子,短信和支付寶就是金額變化的觀察者。
傳統(tǒng)模式
金額數(shù)據(jù)類
public class MoneyData { private BigDecimal amount; private SMS sms; MoneyData(BigDecimal value){ amount = value; sms = new SMS(); } public void increase(BigDecimal value){ amount = amount.add(value); sms.sendMsg("通知:余額+"+value+",現(xiàn)余額為:"+amount); } public void decrease(BigDecimal value){ amount = amount.subtract(value); sms.sendMsg("通知:余額-"+value+",現(xiàn)余額為:"+amount); } }
短信類
public class SMS { public void sendMsg(String str){ System.out.println("短信"+str); } }
客戶端類
public class Client { public static void main(String[] args) { MoneyData moneyData = new MoneyData(new BigDecimal("5.20")); moneyData.increase(new BigDecimal("13.14")); moneyData.decrease(new BigDecimal("13.14")); } } /** * 短信通知:余額+13.14,現(xiàn)余額為:18.34 * 短信通知:余額-13.14,現(xiàn)余額為:5.20 */
傳統(tǒng)模式擴(kuò)展性十分差,如果新增一個(gè)支付寶觀察者,需要修改金額數(shù)據(jù)類,增加一個(gè)成員變量。
違反了ocp原則(開閉原則)。可以通過觀察者模式修改,讓觀察者放入一個(gè)List列表中
觀察者模式
Subject抽象類
public abstract class Subject { protected List<Observer> observers = new LinkedList<>(); public void registerObserver(Observer o) { observers.add(o); } public void removeObserver(Observer o) { if(observers.contains(o)){ observers.remove(o); } } public abstract void notifyObservers(String changeValue); }
Subject 的具體實(shí)現(xiàn)類
public class MoneyData extends Subject{ private BigDecimal amount; MoneyData(BigDecimal value){ this.amount = value; } public void increase(BigDecimal value){ amount = amount.add(value); notifyObservers("+"+value); } public void decrease(BigDecimal value){ amount = amount.subtract(value); notifyObservers("-"+value); } @Override public void notifyObservers(String changeValue) { for (Observer observer : observers) { observer.sendMsg("通知:余額"+changeValue+",現(xiàn)余額為"+amount); } } }
Observer(觀察者)接口
public class SMS implements Observer{ @Override public void sendMsg(String msg) { System.out.println("短信"+msg); } }
Observer(觀察者)的兩個(gè)具體實(shí)現(xiàn)類
public class SMS implements Observer{ @Override public void sendMsg(String msg) { System.out.println("短信"+msg); } }
public class Alipay implements Observer{ @Override public void sendMsg(String msg) { System.out.println("支付寶"+msg); } }
客戶端類
public class Client { public static void main(String[] args) { MoneyData moneyData = new MoneyData(new BigDecimal("13.14")); moneyData.registerObserver(new SMS()); moneyData.increase(new BigDecimal("52.00")); moneyData.decrease(new BigDecimal("52.00")); moneyData.registerObserver(new Alipay()); moneyData.increase(new BigDecimal("5.20")); moneyData.decrease(new BigDecimal("5.20")); } } /** * 短信通知:余額+52.00,現(xiàn)余額為65.14 * 短信通知:余額-52.00,現(xiàn)余額為13.14 * 短信通知:余額+5.20,現(xiàn)余額為18.34 * 支付寶通知:余額+5.20,現(xiàn)余額為18.34 * 短信通知:余額-5.20,現(xiàn)余額為13.14 * 支付寶通知:余額-5.20,現(xiàn)余額為13.14 */
應(yīng)用場(chǎng)景
- 對(duì)象間存在一對(duì)多關(guān)系,一個(gè)對(duì)象的狀態(tài)發(fā)生改變會(huì)影響其他對(duì)象。
- 當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面時(shí),可將這二者封裝在獨(dú)立的對(duì)象中以使它們可以各自獨(dú)立地改變和復(fù)用。
到此這篇關(guān)于Java設(shè)計(jì)模式之觀察者模式的文章就介紹到這了,更多相關(guān)Java觀察者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java對(duì)ArrayList中元素進(jìn)行排序的幾種方式總結(jié)
在Java中,ArrayList類提供了多種排序方法,可以根據(jù)不同的需求選擇適合的排序方法,下面這篇文章主要給大家介紹了關(guān)于java對(duì)ArrayList中元素進(jìn)行排序的幾種方式,需要的朋友可以參考下2024-08-08關(guān)于SpringBoot配置項(xiàng)的優(yōu)先級(jí),不再有配置不生效的問題
這篇文章主要介紹了關(guān)于SpringBoot配置項(xiàng)的優(yōu)先級(jí),不再有配置不生效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04spring事務(wù)隔離級(jí)別、傳播機(jī)制以及簡(jiǎn)單配置方式
這篇文章主要介紹了spring事務(wù)隔離級(jí)別、傳播機(jī)制以及簡(jiǎn)單配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01MyBatis-Plus中MetaObjectHandler沒生效完美解決
在進(jìn)行測(cè)試時(shí)發(fā)現(xiàn)配置的MyMetaObjectHandler并沒有生效,本文主要介紹了MyBatis-Plus中MetaObjectHandler沒生效完美解決,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11Eclipse不自動(dòng)編譯java文件的終極解決方法
這篇文章主要介紹了Eclipse不自動(dòng)編譯java文件的終極解決方法,需要的朋友可以參考下2015-12-12