實例代碼講解JAVA 觀察者模式
當(dāng)對象間存在一對多關(guān)系時,則使用觀察者模式(Observer Pattern)。比如,當(dāng)一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
介紹
意圖:定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。
主要解決:一個對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
何時使用:一個對象(目標(biāo)對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。
如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。
關(guān)鍵代碼:在抽象類里有一個 ArrayList 存放觀察者們。
應(yīng)用實例:
1、拍賣的時候,拍賣師觀察最高標(biāo)價,然后通知給其他競價者競價。
2、西游記里面悟空請求菩薩降服紅孩兒,菩薩灑了一地水招來一個老烏龜,這個烏龜就是觀察者,他觀察菩薩灑水這個動作。
優(yōu)點:
1、觀察者和被觀察者是抽象耦合的。
2、建立一套觸發(fā)機制。
缺點:
1、如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
2、如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話,觀察目標(biāo)會觸發(fā)它們之間進行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰。
3、觀察者模式?jīng)]有相應(yīng)的機制讓觀察者知道所觀察的目標(biāo)對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標(biāo)發(fā)生了變化。
使用場景:
- 一個抽象模型有兩個方面,其中一個方面依賴于另一個方面。將這些方面封裝在獨立的對象中使它們可以各自獨立地改變和復(fù)用。
- 一個對象的改變將導(dǎo)致其他一個或多個對象也發(fā)生改變,而不知道具體有多少對象將發(fā)生改變,可以降低對象之間的耦合度。
- 一個對象必須通知其他對象,而并不知道這些對象是誰。
- 需要在系統(tǒng)中創(chuàng)建一個觸發(fā)鏈,A對象的行為將影響B(tài)對象,B對象的行為將影響C對象……,可以使用觀察者模式創(chuàng)建一種鏈式觸發(fā)機制。
注意事項:
1、JAVA 中已經(jīng)有了對觀察者模式的支持類。
2、避免循環(huán)引用。
3、如果順序執(zhí)行,某一觀察者錯誤會導(dǎo)致系統(tǒng)卡殼,一般采用異步方式。
實現(xiàn)
觀察者模式使用三個類 Subject、Observer 和 Client。Subject 對象帶有綁定觀察者到 Client 對象和從 Client 對象解綁觀察者的方法。我們創(chuàng)建 Subject 類、Observer 抽象類和擴展了抽象類 Observer 的實體類。
ObserverPatternDemo,我們的演示類使用 Subject 和實體類對象來演示觀察者模式。
步驟 1
創(chuàng)建 Subject 類。
import java.util.ArrayList; import java.util.List; public class Subject { private List<Observer> observers = new ArrayList<Observer>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for (Observer observer : observers) { observer.update(); } } }
步驟 2
創(chuàng)建 Observer 類。
public abstract class Observer { protected Subject subject; public abstract void update(); }
步驟 3
創(chuàng)建實體觀察者類。
public class BinaryObserver extends Observer{ public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); } }
public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); } }
public class HexaObserver extends Observer{ public HexaObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); } }
步驟 4
使用 Subject 和實體觀察者對象。
public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); System.out.println("First state change: 15"); subject.setState(15); System.out.println("Second state change: 10"); subject.setState(10); } }
步驟 5
執(zhí)行程序,輸出結(jié)果:
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
以上就是實例代碼講解JAVA 觀察者模式的詳細內(nèi)容,更多關(guān)于JAVA 觀察者模式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Maven本地倉庫明明有對應(yīng)的jar包但還是報找不到的問題
這篇文章主要介紹了解決Maven本地倉庫明明有對應(yīng)的jar包但還是報找不到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10java多線程編程之從線程返回數(shù)據(jù)的兩種方法
從線程中返回數(shù)據(jù)和向線程傳遞數(shù)據(jù)類似。也可以通過類成員以及回調(diào)函數(shù)來返回數(shù)據(jù)。但類成員在返回數(shù)據(jù)和傳遞數(shù)據(jù)時有一些區(qū)別,下面讓我們來看看它們區(qū)別在哪2014-01-01關(guān)于LinkedList集合對元素進行增查刪操作
LinkedList集合內(nèi)部包含有兩個Node類型的first和last屬性維護一個雙向循環(huán)鏈表,在鏈表中的每一個元素都使用引用的方式來記住它的前一個元素和后一個元素,從而可以將所有的元素彼此連接起來,需要的朋友可以參考下2023-04-04SpringBoot打War包上傳到阿里云的LINUX服務(wù)器的操作方法
這篇文章主要介紹了SpringBoot打War包上傳到阿里云的LINUX服務(wù)器,本文通過圖文并茂的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02springboot整合log4j的踩坑實戰(zhàn)記錄
log日志的重要性不言而喻,所以我們需要在系統(tǒng)內(nèi)根據(jù)實際的業(yè)務(wù)進行日志的整合,下面這篇文章主要給大家介紹了關(guān)于springboot整合log4j的踩坑實戰(zhàn)記錄,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2022-04-04關(guān)于SpringBoot打包測試、生產(chǎn)環(huán)境方式
這篇文章主要介紹了關(guān)于SpringBoot打包測試、生產(chǎn)環(huán)境方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09Java為什么匿名內(nèi)部類參數(shù)引用需要用final進行修飾?
今天小編就為大家分享一篇關(guān)于Java為什么匿名內(nèi)部類參數(shù)引用需要用final進行修飾?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié)
本篇文章主要介紹了springboot 使用Spring Boot Actuator監(jiān)控應(yīng)用小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02