欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Java中觀察者模式與委托的對比

 更新時間:2022年05月11日 09:02:57   作者:小小張自由—>張有博  
這篇文章主要介紹了Java中觀察者模式與委托的對比,觀察者模式:定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,委托的實現(xiàn)簡單來講就是用反射來實現(xiàn)的,本文給大家介紹的非常詳細,需要的朋友可以參考下

代碼背景

一個班級,有兩類學生,A類:不學習,玩,但是玩的東西不一樣,有的是做游戲,有的是看電視

B類:放哨的學生,專門看老師的動向,如果老師進班了就立即通知大家。

如此就形成了一個需求,放哨的學生要通知所有玩的學生:老師來了,而不同的學生有不同的反應,有的馬上把電視關閉,有的停止玩游戲。

觀察者模式

介紹

觀察者模式:定義了一種一對多的依賴關系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。
這個主題對象在狀態(tài)發(fā)生變化時,會通知所有的觀察者對象,使他們能夠自動更新自己。

主要解決:一個對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。

何時使用:一個對象(目標對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。

如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關系弱化。

關鍵代碼:在抽象類里有一個 ArrayList 存放觀察者們。

實現(xiàn)

觀察者(學生)

/**
 * 抽象的觀察者
 *
 * @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;
    //觀察者的狀態(tài)
    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的:新狀態(tài)是%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;
    //觀察者的狀態(tài)
    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:新狀態(tài)是%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 {
    //通知者的狀態(tài)
    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) {
        //創(chuàng)建一個主題/通知者
        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);
        //通知者(老師)狀態(tài)修改,通知每個學生
        subject.setSubjectState("老師回來了,我要好好學習");
        subject.notifyMsg();
        System.out.println("-----------");
    }
}

 委托 介紹

委托可以看做是函數(shù)的抽象,是函數(shù)的“類”。委托的實例將代表一個具體的函數(shù)
一個委托可以搭載多個方法,所有的方法被依次喚起??梢允刮袑ο笏钶d的方法并不需要屬于同一類。
委托事件模型可以由三個組件定義:事件、事件源和事件偵聽器。

委托的實現(xiàn)簡單來講就是用反射來實現(xiàn)的。

實現(xiàn)

觀察者

/**
 * 監(jiān)聽器/觀察者 玩游戲
 * 事件監(jiān)聽器
 * @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("老師來了,快回到座位上,結(jié)束時間"+date);
    }
}
/**
 * 監(jiān)聽器/觀察者 看電視
 * 事件監(jiān)聽器
 * @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("老師來了,快關閉電視 。 結(jié)束時間"+date);
    }
}

通知者

/**
 * 通知者的抽象類
 * 事件源
 * @author Promsing(張有博)
 * @version 1.0.0
 * @since 2022/5/8 - 11:15
 */
public abstract class Notifier {
    //每個通知者都有一個需要通知的隊列(通知:對象、方法、參數(shù))
    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{
            //優(yōu)化:異步通知
            this.getEventHandler().notifyX();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

 事件

/**
 * 抽象出的事件類,也可以稱為方法類
 * 事件
 * @author Promsing(張有博)
 * @version 1.0.0
 * @since 2022/5/8 - 11:03
 */
public class Event {
    //要執(zhí)行方法的對象
    private Object object;
    //要執(zhí)行的方法名稱
    private String methodName;
    //要執(zhí)行方法的參數(shù)
    private Object[] params;
    //要執(zhí)行方法的參數(shù)類型
    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);
    }
    //根據(jù)參數(shù)數(shù)組生成參數(shù)類型數(shù)組
    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();
        }
    }
    //執(zhí)行該 對象的該方法
    public void invoke() throws Exception{
        //通過class,method,paramTypes 確定執(zhí)行哪個類的哪個方法
        Method method=object.getClass().getMethod(this.getMethodName(), this.getParamTypes());
        if(null==method){
            return;
        }
        //方法執(zhí)行
        method.invoke(this.getObject(), this.getParams());
    }
}

事件處理

/**
 * 管理哪些事件需要執(zhí)行
 * 管理事件
 *
 * @author Promsing(張有博)
 * @version 1.0.0
 * @since 2022/5/8 - 11:03
 */
public class EventHandler {
    //是用一個List
    private List<Event> objects;
    //添加某個對象要執(zhí)行的事件,及需要的參數(shù)
    public void addEvent(Object object,String methodName,Object...args){
        objects.add(new Event(object,methodName,args));
    }
    public EventHandler(){
        objects=new ArrayList<Event>();
    }
    //通知所有的對象執(zhí)行指定的事件
    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) {
        //創(chuàng)建一個盡職盡責的放哨者
        Notifier goodNotifier = new GoodNotifier();
        //創(chuàng)建一個玩游戲的同學,開始玩游戲
        PlayingGameListener playingGameListener = new PlayingGameListener();
        //創(chuàng)建一個看電視的同學,開始看電視
        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();
        }
        //老師出現(xiàn),放哨的人通知所有要幫忙的同學:老師來了
        goodNotifier.notifyX();
    }
}

 總結(jié)

1.先有觀察者模式后有委托事件技術(shù)
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.委托與觀察者比多了一個事件執(zhí)行者,解除觀察者與通知者的耦合,可以做到通知任何對象的任何方法。讓A類學生和B類學生完全解耦,即A類完全不知道B類的學生,卻可以通知B類的學生

6.建立一套觸發(fā)機制,可以使用異步通知

7.觀察者/委托挺像MQ里邊的訂閱發(fā)布。生產(chǎn)者、隊列、消費者。

到此這篇關于Java中觀察者模式與委托的對比的文章就介紹到這了,更多相關Java觀察者模式委托內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • SpringBoot整合Swagger框架過程解析

    SpringBoot整合Swagger框架過程解析

    這篇文章主要介紹了SpringBoot整合Swagger框架過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • spring cloud gateway轉(zhuǎn)發(fā)服務報錯的解決

    spring cloud gateway轉(zhuǎn)發(fā)服務報錯的解決

    這篇文章主要介紹了spring cloud gateway轉(zhuǎn)發(fā)服務報錯的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 一文搞懂Mybatis-plus的分頁查詢操作

    一文搞懂Mybatis-plus的分頁查詢操作

    說起分頁機制,相信我們程序員都不陌生,今天,我就給大家分享一下Mybatis-plus的分頁機制,供大家學習和Copy,感興趣的可以了解一下
    2022-06-06
  • 創(chuàng)建并運行一個java線程方法介紹

    創(chuàng)建并運行一個java線程方法介紹

    這篇文章主要介紹了創(chuàng)建并運行一個java線程,涉及線程代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java doGet, doPost方法和文件上傳實例代碼

    Java doGet, doPost方法和文件上傳實例代碼

    這篇文章主要介紹了Java doGet, doPost方法和文件上傳實例代碼的相關資料,需要的朋友可以參考下
    2016-11-11
  • Java圖形化界面設計之容器(JFrame)詳解

    Java圖形化界面設計之容器(JFrame)詳解

    這篇文章主要介紹了Java圖形化界面設計之容器(JFrame)詳解,條理清晰,依次介紹了Java基本類(JFC),AWT和Swing的區(qū)別,Swing基本框架,圖形化設計步驟以及組件容器的使用等相關內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 命令提示符編譯java的方法(必看篇)

    命令提示符編譯java的方法(必看篇)

    下面小編就為大家?guī)硪黄钐崾痉幾gjava的方法(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • JPA中EntityListeners注解的使用詳解

    JPA中EntityListeners注解的使用詳解

    這篇文章主要介紹了JPA中EntityListeners注解的使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • Java實現(xiàn)Ip地址獲取的示例代碼

    Java實現(xiàn)Ip地址獲取的示例代碼

    這篇文章主要為大家詳細介紹了Java實現(xiàn)Ip地址獲取的兩種方式,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考一下
    2023-09-09
  • java類中生成jfreechart,返回圖表的url地址 代碼分享

    java類中生成jfreechart,返回圖表的url地址 代碼分享

    這篇文章介紹了java類中生成jfreechart,返回圖表的url地址的代碼,有需要的朋友可以參考一下
    2013-08-08

最新評論