最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

代碼背景

一個(gè)班級,有兩類學(xué)生,A類:不學(xué)習(xí),玩,但是玩的東西不一樣,有的是做游戲,有的是看電視

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

如此就形成了一個(gè)需求,放哨的學(xué)生要通知所有玩的學(xué)生:老師來了,而不同的學(xué)生有不同的反應(yīng),有的馬上把電視關(guān)閉,有的停止玩游戲。

觀察者模式

介紹

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

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

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

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

關(guān)鍵代碼:在抽象類里有一個(gè) ArrayList 存放觀察者們。

實(shí)現(xiàn)

觀察者(學(xué)生)

/**
 * 抽象的觀察者
 *
 * @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)建一個(gè)主題/通知者
        ConcreteSubject subject=new ConcreteSubject();
        //new出觀察者(學(xué)生)
        ConcreteObserver studentZhang = new ConcreteObserver("小張", subject);
        ConcreteObserver studentLiu = new ConcreteObserver("小劉", subject);
        ConcreteObserver studentWang = new ConcreteObserver("小王", subject);
        //將觀察者添加到通知隊(duì)列里
        subject.add(studentZhang);
        subject.add(studentLiu);
        subject.add(studentWang);
        //通知者(老師)狀態(tài)修改,通知每個(gè)學(xué)生
        subject.setSubjectState("老師回來了,我要好好學(xué)習(xí)");
        subject.notifyMsg();
        System.out.println("-----------");
    }
}

 委托 介紹

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

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

實(shí)現(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("我正在玩游戲 開始時(shí)間"+new Date());
    }
    public void stopPlayingGame(Date date){
        System.out.println("老師來了,快回到座位上,結(jié)束時(shí)間"+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("老師來了,快關(guān)閉電視 。 結(jié)束時(shí)間"+date);
    }
}

通知者

/**
 * 通知者的抽象類
 * 事件源
 * @author Promsing(張有博)
 * @version 1.0.0
 * @since 2022/5/8 - 11:15
 */
public abstract class Notifier {
    //每個(gè)通知者都有一個(gè)需要通知的隊(duì)列(通知:對象、方法、參數(shù))
    private EventHandler eventHandler=new EventHandler();
    public EventHandler getEventHandler() {
        return eventHandler;
    }
    public void setEventHandler(EventHandler eventHandler) {
        this.eventHandler = eventHandler;
    }
    //增加需要幫忙放哨的學(xué)生
    public abstract void addListener(Object object,String methodName,Object...args);
    //告訴所有要幫忙放哨的學(xué)生:老師來了
    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("有新的同學(xué)委托盡職盡責(zé)的放哨人!");
        this.getEventHandler().addEvent(object, methodName, args);
    }
    @Override
    public void notifyX() {
        System.out.println("盡職盡責(zé)的放哨人告訴所有需要幫忙的同學(xué):老師來了");
        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í)行哪個(gè)類的哪個(gè)方法
        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 {
    //是用一個(gè)List
    private List<Event> objects;
    //添加某個(gè)對象要執(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)建一個(gè)盡職盡責(zé)的放哨者
        Notifier goodNotifier = new GoodNotifier();
        //創(chuàng)建一個(gè)玩游戲的同學(xué),開始玩游戲
        PlayingGameListener playingGameListener = new PlayingGameListener();
        //創(chuàng)建一個(gè)看電視的同學(xué),開始看電視
        WatchingTVListener watchingTVListener = new WatchingTVListener();
        //玩游戲的同學(xué)告訴放哨的同學(xué),老師來了告訴一下
        goodNotifier.addListener(playingGameListener, "stopPlayingGame", new Date());
        //看電視的同學(xué)告訴放哨的同學(xué),老師來了告訴一下
        goodNotifier.addListener(watchingTVListener, "stopWatchingTV", new Date());
        try {
            //一點(diǎn)時(shí)間后
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //老師出現(xiàn),放哨的人通知所有要幫忙的同學(xué):老師來了
        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.委托與觀察者比多了一個(gè)事件執(zhí)行者,解除觀察者與通知者的耦合,可以做到通知任何對象的任何方法。讓A類學(xué)生和B類學(xué)生完全解耦,即A類完全不知道B類的學(xué)生,卻可以通知B類的學(xué)生

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

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

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

相關(guān)文章

  • Java StackTraceElement實(shí)例代碼

    Java StackTraceElement實(shí)例代碼

    這篇文章主要介紹了Java StackTraceElement實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • SSH框架的常見問題和解決方法

    SSH框架的常見問題和解決方法

    SSH框架的常見問題和解決方法,需要的朋友可以參考一下
    2013-02-02
  • 淺談java中Map的用法

    淺談java中Map的用法

    Map簡介:將鍵映射到值的對象。一個(gè)映射不能包含重復(fù)的鍵;每個(gè)鍵最多只能映射到一個(gè)值。此接口取代 Dictionary 類,后者完全是一個(gè)抽象類,而不是一個(gè)接口。
    2015-09-09
  • idea新建maven項(xiàng)目沒有src目錄的操作方法

    idea新建maven項(xiàng)目沒有src目錄的操作方法

    這篇文章主要介紹了idea新建maven項(xiàng)目沒有src目錄的兩種操作方法,需要的朋友可以參考下
    2018-03-03
  • spring mvc中的@PathVariable獲得請求url中的動態(tài)參數(shù)

    spring mvc中的@PathVariable獲得請求url中的動態(tài)參數(shù)

    本文主要介紹了spring mvc中的@PathVariable獲得請求url中的動態(tài)參數(shù)的代碼。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • 一學(xué)即會之JDK版本快速切換方法(2024)

    一學(xué)即會之JDK版本快速切換方法(2024)

    這篇文章主要介紹了一學(xué)即會之JDK版本快速切換方法,詳細(xì)給大家講解了如何下載、安裝和配置多個(gè)JDK版本,并通過設(shè)置環(huán)境變量和編寫批處理腳本來切換JDK版本,需要的朋友可以參考下
    2025-03-03
  • Spring體系的各種啟動流程詳解

    Spring體系的各種啟動流程詳解

    這篇文章主要給大家介紹了關(guān)于Spring體系的各種啟動流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • zookeeper集群搭建超詳細(xì)過程

    zookeeper集群搭建超詳細(xì)過程

    這篇文章主要介紹了zookeeper集群搭建超詳細(xì)過程,本文對zookeeper集群測試通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • mybatis plus in使用時(shí)傳數(shù)組、集合的注意點(diǎn)說明

    mybatis plus in使用時(shí)傳數(shù)組、集合的注意點(diǎn)說明

    這篇文章主要介紹了mybatis plus in使用時(shí)傳數(shù)組、集合的注意點(diǎn)說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Java平閏年判斷的方法總結(jié)

    Java平閏年判斷的方法總結(jié)

    本篇文章給大家整理了Java平閏年判斷的兩種方法,大家在寫程序的時(shí)候如果用的到參考下吧。
    2018-02-02

最新評論

当阳市| 华安县| 清水县| 太仓市| 山丹县| 五峰| 南木林县| 新郑市| 和田县| 湖南省| 棋牌| 孝感市| 西城区| 延津县| 茂名市| 青铜峡市| 泗阳县| 重庆市| 酉阳| 南汇区| 砀山县| 绍兴县| 西乌珠穆沁旗| 章丘市| 嘉祥县| 芮城县| 桑日县| 平利县| 绿春县| 海阳市| 乾安县| 航空| 民权县| 临汾市| 新丰县| 赞皇县| 昭觉县| 吕梁市| 嵊泗县| 黎平县| 福安市|