java 观察者模式示例_观察者设计模式示例
java 觀察者模式示例
本文是我們名為“ Java設計模式 ”的學院課程的一部分。
在本課程中,您將深入研究大量的設計模式,并了解如何在Java中實現和利用它們。 您將了解模式如此重要的原因,并了解何時以及如何應用模式中的每一個。 在這里查看 !
目錄
1.觀察者模式 2.什么是觀察者模式 3.實施觀察者模式 4. Java的內置觀察者模式 5.何時使用觀察者模式 6.下載源代碼1.觀察者模式
體育大廳是運動愛好者的理想運動場所。 它們涵蓋幾乎所有類型的體育活動,并提供最新新聞,信息,比賽預定日期,有關特定球員或球隊的信息。 現在,他們計劃提供實時評論或比賽分數作為SMS服務,但僅針對其高級用戶。 他們的目標是在短時間間隔后通過短信發送實時比分,比賽情況和重要事件。 作為用戶,您需要訂閱該程序包,并且在進行實時比賽時,您會收到一條有關實時評論的短信。 該站點還提供了一個隨時取消訂閱包的選項。
作為開發人員,運動大廳要求您為他們提供此新功能。 體育大廳的記者將坐在比賽中的評論框內,并將實時評論更新為評論對象。 作為開發人員,您的工作是通過從評論對象(如果有)中獲取評論來向注冊用戶提供評論。 進行更新時,系統應通過向訂閱的用戶發送SMS來更新他們。
這種情況清楚地顯示了比賽與用戶之間的一對多映射,因為可能有許多用戶訂閱單個比賽。 觀察者設計模式最適合這種情況,讓我們了解一下這種模式,然后為Sport Lobby創建功能。
2.什么是觀察者模式
觀察者模式是一種行為模式,它與對象之間的職責分配有關。 行為模式表征了復雜的控制流,這些流在運行時很難遵循。 它們將您的注意力從控制流上移開,讓您僅專注于對象的互連方式。
觀察者模式定義了對象之間的一對多依賴關系,因此當一個對象改變狀態時,其所有依賴關系都會得到通知并自動更新。 觀察者模式描述了這些依賴關系。 此模式中的關鍵對象是主題和觀察者。 主題可以具有任意數量的從屬觀察者。 只要對象的狀態發生變化,就會通知所有觀察者。 作為響應,每個觀察者將查詢主題以使其狀態與主題狀態同步。
了解觀察者模式的另一種方法是發布者與訂閱者之間的關系。 例如,假設您訂閱了自己喜歡的體育或時尚雜志的雜志。 每當發行新期刊時,它就會交付給您。 如果您在不再需要該雜志時取消訂閱,則該雜志將不會發送給您。 但是出版商繼續像以前一樣工作,因為還有其他人也訂閱了該雜志。
圖1
觀察者模式有四個參與者:
3.實施觀察者模式
讓我們看看如何在開發運動大廳功能時使用觀察者模式。 有人將更新具體主題的對象,而您的工作是更新在具體主題對象中注冊的對象的狀態。 因此,只要具體主體對象的狀態發生變化,就應該通知其所有依賴對象,然后進行更新。
圖2
基于此,我們首先創建一個Subject接口。 在“主題”界面中,有三種主要方法,可以根據需要添加其他一些方法(如果需要)。
package com.javacodegeeks.patterns.observerpattern;public interface Subject {public void subscribeObserver(Observer observer);public void unSubscribeObserver(Observer observer);public void notifyObservers();public String subjectDetails(); }“ Subject界面中的三個關鍵方法是:
并且可選地,還有一個方法subjectDetails() ,這是一個簡單的方法,并且根據您的需要。 在這里,其工作是返回主題的詳細信息。
現在,讓我們看看Observer界面。
package com.javacodegeeks.patterns.observerpattern;public interface Observer {public void update(String desc);public void subscribe();public void unSubscribe(); }報告者使用以上接口來更新評論對象的實時評論。 這是一個可選接口,僅用于遵循代碼與接口的原則 ,與Observer模式無關。 您應該在適用的情況下應用oops原則以及設計模式。 該界面僅包含一種用于更改具體主題對象狀態的方法。
package com.javacodegeeks.patterns.observerpattern;import java.util.List;public class CommentaryObject implements Subject,Commentary{private final List<Observer>observers;private String desc;private final String subjectDetails;public CommentaryObject(List<Observer>observers,String subjectDetails){this.observers = observers;this.subjectDetails = subjectDetails;}@Overridepublic void subscribeObserver(Observer observer) {observers.add(observer);}@Overridepublic void unSubscribeObserver(Observer observer) {int index = observers.indexOf(observer);observers.remove(index);}@Overridepublic void notifyObservers() {System.out.println();for(Observer observer : observers){observer.update(desc);}}@Overridepublic void setDesc(String desc) {this.desc = desc;notifyObservers();}@Overridepublic String subjectDetails() {return subjectDetails;}}上面的類用作實現Subject接口并提供其實現的具體主題。 它還將引用存儲到已注冊的觀察者。
package com.javacodegeeks.patterns.observerpattern;public class SMSUsers implements Observer{private final Subject subject;private String desc;private String userInfo;public SMSUsers(Subject subject,String userInfo){if(subject==null){throw new IllegalArgumentException("No Publisher found.");}this.subject = subject;this.userInfo = userInfo;}@Overridepublic void update(String desc) {this.desc = desc;display();}private void display(){System.out.println("["+userInfo+"]: "+desc);}@Overridepublic void subscribe() {System.out.println("Subscribing "+userInfo+" to "+subject.subjectDetails()+" ...");this.subject.subscribeObserver(this);System.out.println("Subscribed successfully.");}@Overridepublic void unSubscribe() {System.out.println("Unsubscribing "+userInfo+" to "+subject.subjectDetails()+" ...");this.subject.unSubscribeObserver(this);System.out.println("Unsubscribed successfully.");}}上面的類是實現Observer接口的具體觀察者類。 它還存儲對它訂閱的主題的引用,以及可選的用于顯示用戶信息的userInfo變量。
現在,讓我們測試示例。
package com.javacodegeeks.patterns.observerpattern;import java.util.ArrayList;public class TestObserver {public static void main(String[] args) {Subject subject = new CommentaryObject(new ArrayList<Observer>(), "Soccer Match [2014AUG24]");Observer observer = new SMSUsers(subject, "Adam Warner [New York]");observer.subscribe();System.out.println();Observer observer2 = new SMSUsers(subject, "Tim Ronney [London]");observer2.subscribe();Commentary cObject = ((Commentary)subject);cObject.setDesc("Welcome to live Soccer match");cObject.setDesc("Current score 0-0");System.out.println();observer2.unSubscribe();System.out.println();cObject.setDesc("It's a goal!!");cObject.setDesc("Current score 1-0");System.out.println();Observer observer3 = new SMSUsers(subject, "Marrie [Paris]");observer3.subscribe();System.out.println();cObject.setDesc("It's another goal!!");cObject.setDesc("Half-time score 2-0");}}上面的示例將產生以下輸出:
Subscribing Adam Warner [New York] to Soccer Match [2014AUG24] ... Subscribed successfully.Subscribing Tim Ronney [London] to Soccer Match [2014AUG24] ... Subscribed successfully.[Adam Warner [New York]]: Welcome to live Soccer match [Tim Ronney [London]]: Welcome to live Soccer match[Adam Warner [New York]]: Current score 0-0 [Tim Ronney [London]]: Current score 0-0Unsubscribing Tim Ronney [London] to Soccer Match [2014AUG24] ... Unsubscribed successfully.[Adam Warner [New York]]: It's a goal!![Adam Warner [New York]]: Current score 1-0Subscribing Marrie [Paris] to Soccer Match [2014AUG24] ... Subscribed successfully.[Adam Warner [New York]]: It's another goal!! [Marrie [Paris]]: It's another goal!![Adam Warner [New York]]: Half-time score 2-0 [Marrie [Paris]]: Half-time score 2-0如您所見,起初有兩個用戶訂閱了足球比賽并開始接收評論。 但是后來有一個用戶取消了訂閱,因此該用戶沒有再收到評論。 然后,另一個用戶訂閱并開始獲取評論。
所有這一切都是動態發生的,無需更改現有代碼,不僅如此,假設該公司是否要在電子郵件上廣播評論,或者任何其他公司希望與該公司進行合作以廣播評論。 您需要做的就是創建兩個新類,例如UserEmail和ColCompany并通過實現Observer接口使它們成為主題的Observer 。 據Subject知道它是觀察者,它將提供更新。
4. Java的內置觀察者模式
Java內置了對Observer模式的支持。 最通用的是java.util包中的Observer接口和Observable類。 這些與我們的“主題和觀察者”界面非常相似,但是為您提供了許多現成的功能。
讓我們嘗試使用Java的內置Observer模式實現上述示例。
package com.javacodegeeks.patterns.observerpattern;import java.util.Observable;public class CommentaryObjectObservable extends Observable implements Commentary {private String desc;private final String subjectDetails;public CommentaryObjectObservable(String subjectDetails){this.subjectDetails = subjectDetails;}@Overridepublic void setDesc(String desc) {this.desc = desc;setChanged();notifyObservers(desc);}public String subjectDetails() {return subjectDetails;} }這次我們擴展了Observable類,使我們的類成為一個主體,請注意,上述類沒有任何對觀察者的引用,它是由父類處理的,即Observable類。 但是,我們聲明了setDesc方法來更改對象的狀態,如上例所示。 setChanged方法是上層類的方法,用于將更改的標志設置為true。 notifyObservers方法通知其所有觀察者,然后調用clearChanged方法以指示此對象不再更改。 每個觀察者都有使用兩個參數調用的update方法:一個observable對象和arg參數。
package com.javacodegeeks.patterns.observerpattern;import java.util.Observable;public class SMSUsersObserver implements java.util.Observer{private String desc;private final String userInfo;private final Observable observable;public SMSUsersObserver(Observable observable,String userInfo){this.observable = observable;this.userInfo = userInfo;}public void subscribe() {System.out.println("Subscribing "+userInfo+" to "+((CommentaryObjectObservable)(observable)).subjectDetails()+" ...");this.observable.addObserver(this);System.out.println("Subscribed successfully.");}public void unSubscribe() {System.out.println("Unsubscribing "+userInfo+" to "+((CommentaryObjectObservable)(observable)).subjectDetails()+" ...");this.observable.deleteObserver(this);System.out.println("Unsubscribed successfully.");}@Overridepublic void update(Observable o, Object arg) {desc = (String)arg;display();}private void display(){System.out.println("["+userInfo+"]: "+desc);}}讓我們討論一些關鍵方法。
上面的類實現了Observer接口,該接口具有一個關鍵方法update ,當主題調用notifyObservers方法時會調用該方法。 update方法采用一個Observable對象和一個arg作為參數。
addObserver方法用于將觀察者注冊到主題,而deleteObserver方法用于將觀察者從主題列表中刪除。
讓我們測試這個例子。
package com.javacodegeeks.patterns.observerpattern;public class Test {public static void main(String[] args) {CommentaryObjectObservable obj = new CommentaryObjectObservable("Soccer Match [2014AUG24]");SMSUsersObserver observer = new SMSUsersObserver(obj, "Adam Warner [New York]");SMSUsersObserver observer2 = new SMSUsersObserver(obj,"Tim Ronney [London]");observer.subscribe();observer2.subscribe();System.out.println("------------------------------------------------------");obj.setDesc("Welcome to live Soccer match");obj.setDesc("Current score 0-0");observer.unSubscribe();obj.setDesc("It's a goal!!");obj.setDesc("Current score 1-0");} }上面的示例將產生以下輸出:
Subscribing Adam Warner [New York] to Soccer Match [2014AUG24] ... Subscribed successfully. Subscribing Tim Ronney [London] to Soccer Match [2014AUG24] ... Subscribed successfully. ------------------------------------------------------ [Tim Ronney [London]]: Welcome to live Soccer match [Adam Warner [New York]]: Welcome to live Soccer match [Tim Ronney [London]]: Current score 0-0 [Adam Warner [New York]]: Current score 0-0 Unsubscribing Adam Warner [New York] to Soccer Match [2014AUG24] ... Unsubscribed successfully. [Tim Ronney [London]]: It's a goal!! [Tim Ronney [London]]: Current score 1-0上面的類創建一個主題和兩個觀察者。 observer的subscribe方法將其自身添加到主題觀察者列表中。 然后setDesc更改主題的狀態,該主題調用setChanged方法將更改標志設置為true,并通知觀察者。 結果,調用了觀察者的update方法,該方法在內部對display方法進行分類以顯示結果。 后來,一位觀察者unsubscribe d,即從觀察者列表中將其刪除。 由于此原因,以后的評論未更新。
Java為觀察者模式提供了內置功能,但是它也有其自身的缺點。 Observable是一個類,您必須對其進行子類化。 這意味著您不能將Observable行為添加到已經擴展了另一個超類的現有類上。 這限制了重用潛力。 您甚至無法創建自己的實現,以與Java的內置Observer API配合使用。 Observable API中的某些方法受到保護。 這意味著除非已將Observable子類setChange否則無法調用setChange類的方法。 而且,您甚至無法創建Observable類的實例并將其與自己的對象組合在一起,因此必須子類化。 此設計違反了“優先繼承而不是繼承”的設計原則。
5.何時使用觀察者模式
在以下任何一種情況下,請使用Observer模式:
6.下載源代碼
這是“觀察者模式”的一課。 您可以在此處下載源代碼: ObserverPattern –第7課
翻譯自: https://www.javacodegeeks.com/2015/09/observer-design-pattern.html
java 觀察者模式示例
總結
以上是生活随笔為你收集整理的java 观察者模式示例_观察者设计模式示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cdr图层锁定快捷键(cdr上移一层快捷
- 下一篇: 红色警戒电脑安装包(蓝色警戒电脑版安装包