程式碼背景
一個班級,有兩類學生,A類別:不學習,玩,但是玩的東西不一樣,有的是做遊戲,有的是看電視
B類:放哨的學生,專門看老師的動向,如果老師進班了就立刻通知大家。
如此就形成了一個需求,放哨的學生要通知所有玩的學生:老師來了,而不同的學生有不同的反應,有的馬上把電視關閉,有的停止玩遊戲。
觀察者模式
介紹
觀察者模式:定義了一個一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題對象。
這個主題對像在狀態改變時,會通知所有的觀察者對象,使他們能夠自動更新自己。
主要解決:一個物件狀態改變給其他物件通知的問題,而且要考慮到易用和低耦合,保證高度的協作。
何時使用:一個物件(目標物件)的狀態改變,所有的依賴物件(觀察者物件)都會被通知,進行廣播通知。
如何解決:使用物件導向技術,可以將這種依賴關係弱化。
關鍵程式碼:在抽象類別裡有一個 ArrayList 存放觀察者。
實作
觀察者(學生)
/** * 抽象的观察者 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:32 */ public interface Observer { public abstract void updateState(); } /** * 具体的观察者 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:39 */ public class ConcreteObserver implements Observer{ //观察者的姓名 private String name; //观察者的状态 private String observerState; //明确具体的通知者 private ConcreteSubject subject; //get set方法省略 public ConcreteObserver(String name, ConcreteSubject subject) { this.name = name; this.subject = subject; } @Override public void updateState() { observerState=subject.getSubjectState(); System.out.println(name+"在打游戏"); String str=String.format("观察者%s的:新状态是%s", name,observerState); System.out.println(str); } } /** * 具体的观察者 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:39 */ public class ConcreteObserver2 implements Observer{ //观察者的姓名 private String name; //观察者的状态 private String observerState; //明确具体的通知者 private ConcreteSubject subject; //get set方法省略 public ConcreteObserver2(String name, ConcreteSubject subject) { this.name = name; this.subject = subject; } @Override public void updateState() { observerState=subject.getSubjectState(); System.out.println(name+"在看电视"); String str=String.format("观察者%s:新状态是%s", name,observerState); System.out.println(str); } }
通知者(老師)
/** * 抽象的通知者 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:30 */ public abstract class Subject { //管理观察者的集合 private List<Observer> observers=new ArrayList<>(); //增加观察者 public void add(Observer observer){ observers.add(observer); } //减少观察者 public void detach(Observer observer){ observers.remove(observer); } /** * 通知所有的观察者 */ public void notifyMsg(){ for (Observer observer : observers) { observer.updateState(); } } } /** * 具体的通知者 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:38 */ public class ConcreteSubject extends Subject { //通知者的状态 private String subjectState; //get set方法 public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; } }
Main方法
/** * 控制台Main方法 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/10 - 15:48 */ public class MainTest { public static void main(String[] args) { //创建一个主题/通知者 ConcreteSubject subject=new ConcreteSubject(); //new出观察者(学生) ConcreteObserver studentZhang = new ConcreteObserver("小张", subject); ConcreteObserver studentLiu = new ConcreteObserver("小刘", subject); ConcreteObserver studentWang = new ConcreteObserver("小王", subject); //将观察者添加到通知队列里 subject.add(studentZhang); subject.add(studentLiu); subject.add(studentWang); //通知者(老师)状态修改,通知每个学生 subject.setSubjectState("老师回来了,我要好好学习"); subject.notifyMsg(); System.out.println("-----------"); } }
委託介紹
#委託可以看做是函數的抽象,是函數的「類別」。委託的實例將代表一個具體的函數
一個委託可以搭載多個方法,所有的方法都被依次喚起。可以使委託對象所搭載的方法並不需要屬於同一類。
委託事件模型可以由三個元件定義:事件、事件來源和事件偵聽器。
委託的實作簡單來講就是用反射來實現的。
實作
觀察者
/** * 监听器/观察者 玩游戏 * 事件监听器 * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:17 */ public class PlayingGameListener { public PlayingGameListener(){ System.out.println("我正在玩游戏 开始时间"+new Date()); } public void stopPlayingGame(Date date){ System.out.println("老师来了,快回到座位上,结束时间"+date); } } /** * 监听器/观察者 看电视 * 事件监听器 * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:17 */ public class WatchingTVListener { public WatchingTVListener(){ System.out.println("我正在看电视 "+new Date()); } public void stopWatchingTV(Date date){ System.out.println("老师来了,快关闭电视 。 结束时间"+date); } }
通知者
/** * 通知者的抽象类 * 事件源 * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:15 */ public abstract class Notifier { //每个通知者都有一个需要通知的队列(通知:对象、方法、参数) private EventHandler eventHandler=new EventHandler(); public EventHandler getEventHandler() { return eventHandler; } public void setEventHandler(EventHandler eventHandler) { this.eventHandler = eventHandler; } //增加需要帮忙放哨的学生 public abstract void addListener(Object object,String methodName,Object...args); //告诉所有要帮忙放哨的学生:老师来了 public abstract void notifyX(); } /** * 通知者的子类,放哨人 * 事件源 * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:15 */ public class GoodNotifier extends Notifier { @Override public void addListener(Object object, String methodName, Object...args) { System.out.println("有新的同学委托尽职尽责的放哨人!"); this.getEventHandler().addEvent(object, methodName, args); } @Override public void notifyX() { System.out.println("尽职尽责的放哨人告诉所有需要帮忙的同学:老师来了"); try{ //优化:异步通知 this.getEventHandler().notifyX(); }catch(Exception e){ e.printStackTrace(); } } }
事件
/** * 抽象出的事件类,也可以称为方法类 * 事件 * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:03 */ public class Event { //要执行方法的对象 private Object object; //要执行的方法名称 private String methodName; //要执行方法的参数 private Object[] params; //要执行方法的参数类型 private Class[] paramTypes; //若干setter getter public Object getObject() { return object; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Object[] getParams() { return params; } public void setParams(Object[] params) { this.params = params; } public Class[] getParamTypes() { return paramTypes; } public void setParamTypes(Class[] paramTypes) { this.paramTypes = paramTypes; } public Event(){ } public Event(Object object,String methodName,Object...args){ this.object=object; this.methodName=methodName; this.params=args; contractParamTypes(this.params); } //根据参数数组生成参数类型数组 private void contractParamTypes(Object[] params){ this.paramTypes=new Class[params.length]; for(int i=0;i<params.length;i++){ this.paramTypes[i]=params[i].getClass(); } } //执行该 对象的该方法 public void invoke() throws Exception{ //通过class,method,paramTypes 确定执行哪个类的哪个方法 Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes()); if(null==method){ return; } //方法执行 method.invoke(this.getObject(), this.getParams()); } }
事件處理
/** * 管理哪些事件需要执行 * 管理事件 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:03 */ public class EventHandler { //是用一个List private List<Event> objects; //添加某个对象要执行的事件,及需要的参数 public void addEvent(Object object,String methodName,Object...args){ objects.add(new Event(object,methodName,args)); } public EventHandler(){ objects=new ArrayList<Event>(); } //通知所有的对象执行指定的事件 public void notifyX() throws Exception{ for(Event e : objects){ e.invoke(); } } }
Main方法
/** * 启动类 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/5/8 - 11:19 */ public class EventMain { public static void main(String[] args) { //创建一个尽职尽责的放哨者 Notifier goodNotifier = new GoodNotifier(); //创建一个玩游戏的同学,开始玩游戏 PlayingGameListener playingGameListener = new PlayingGameListener(); //创建一个看电视的同学,开始看电视 WatchingTVListener watchingTVListener = new WatchingTVListener(); //玩游戏的同学告诉放哨的同学,老师来了告诉一下 goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date()); //看电视的同学告诉放哨的同学,老师来了告诉一下 goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date()); try { //一点时间后 Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } //老师出现,放哨的人通知所有要帮忙的同学:老师来了 goodNotifier.notifyX(); } }
總結
1.先有觀察者模式後有委託事件技術
2.觀察者模式只能通知繼承Observer類別的子類,也可以將Observer改成介面
for (Observer observer : observers) { observer.updateState(); }
3.委託可以通知任何類別的任何方法。反射、everone
Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes()); if(null==method){ return; } method.invoke(this.getObject(), this.getParams());
4.委託與觀察者比多了一個事件執行者,解除觀察者與通知者的耦合,可以做到通知任何物件的任何方法。讓A類學生和B類學生完全解耦,也就是A類完全不知道B類的學生,卻可以通知B類的學生
6.建立一套觸發機制,可以使用非同步通知
7.觀察者/委託挺像MQ裡邊的訂閱發布。生產者、隊列、消費者。
以上是Java中觀察者模式與委託的實例比較分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。