ホームページ  >  記事  >  Java  >  Java におけるオブザーバー パターンと委任の例の比較分析

Java におけるオブザーバー パターンと委任の例の比較分析

WBOY
WBOY転載
2023-05-08 16:37:08787ブラウズ

    コードの背景

    クラスには 2 つのタイプの生徒がいます。タイプ A: 勉強せず、遊んでいますが、別のことをしていて、ゲームをしている人もいます。テレビを見ている生徒もいます。

    カテゴリー B: 教師の動きを監視し、教師がクラスに入るとすぐに全員に知らせる見張りの生徒。

    これは需要を生みます。見張りの生徒は、遊んでいる生徒全員に通知する必要があります。先生が来ると、生徒によって反応が異なります。すぐにテレビを消す子もいれば、ゲームをやめる子もいます。

    オブザーバー パターン

    概要

    オブザーバー パターン: 1 対多の依存関係を定義し、複数のオブザーバー オブジェクトがトピック オブジェクトを監視できるようにします。
    このトピック オブジェクトの状態が変化すると、すべてのオブザーバー オブジェクトに通知され、オブザーバー オブジェクトが自動的に更新されるようになります。

    主な解決策: オブジェクトのステータス変更を他のオブジェクトに通知し、高度なコラボレーションを確保するために使いやすさと低結合を考慮する問題。

    いつ使用するか: オブジェクト (ターゲット オブジェクト) の状態が変化すると、すべての依存オブジェクト (オブザーバー オブジェクト) に通知され、ブロードキャスト通知が行われます。

    解決方法: オブジェクト指向テクノロジを使用すると、この依存関係を弱めることができます。

    キー コード: 抽象クラスにはオブザーバーを格納する ArrayList があります。

    実装

    Java におけるオブザーバー パターンと委任の例の比較分析

    観察者 (学生)
    /**
     * 抽象的观察者
     *
     * @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("-----------");
        }
    }

    Java におけるオブザーバー パターンと委任の例の比較分析

    委任の概要

    委任は、関数の抽象化および関数の「クラス」とみなすことができます。デリゲートのインスタンスは特定の関数を表します。
    デリゲートは複数のメソッドを実行でき、すべてのメソッドが順番に呼び出されます。デリゲート オブジェクトによって実行されるメソッドは、同じクラスである必要はありません。
    委任されたイベント モデルは、イベント、イベント ソース、イベント リスナーの 3 つのコンポーネントによって定義できます。

    委任の実装は、リフレクションを使用して簡単に実装されます。

    実装

    Java におけるオブザーバー パターンと委任の例の比較分析

    オブザーバー
    /**
     * 监听器/观察者 玩游戏
     * 事件监听器
     * @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);
        }
    }
    Notifier
    /**
     * 通知者的抽象类
     * 事件源
     * @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();
            }
        }
    }

    メイン メソッド

    /**
     * 启动类
     *
     * @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();
        }
    }

    Java におけるオブザーバー パターンと委任の例の比較分析

    概要

    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. デリゲートにはオブザーバーよりも 1 つ多いイベント エグゼキューターがあり、オブザーバーと通知機能を切り離し、任意のオブジェクトの任意のメソッドに通知できます。タイプ A の生徒とタイプ B の生徒を完全に分離します。つまり、タイプ A はタイプ B の生徒をまったく知りませんが、タイプ B の生徒には通知できます

    6。トリガー メカニズムを確立すると、次のことができます。非同期通知を使用する

    7. オブザーバー/デリゲートは、MQ でのサブスクリプション発行と非常によく似ています。プロデューサー、キュー、コンシューマー。

    以上がJava におけるオブザーバー パターンと委任の例の比較分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。