观察者模式与事件委托

Posted 离线de日常

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式与事件委托相关的知识,希望对你有一定的参考价值。

情景

  • 平时很多人都会用新浪微博, 关注女神动态, 女神就是通知者,也叫主题, 而关注女神的这些人,就是观察者,也叫订阅者, 既然订阅了女神的动态, 如果女神有新的动态, 我们就会想通过某一个渠道被通知, 这种交互方式就是观察者模式

常见的使用场景;

  • spring中的event, listener等都是观察者模式

代码实现

 /**
     * 通知者, 也是主题发布者, 就是为了被观察或者订阅的,
     * 主题如果状态发生改变,就会通知所有的订阅者(观察者)
     */
public interface Subject {
    void addFans(Observer fans);
    void deleteFans(Observer fans);
    void notifyFans();

    void addFansWithEventListener(Observer fans, String event);
    void statusChange();
}
  /**
     * 屌丝朋友们都爱关注的刘亦菲仙女
     */
public class LiuYiFei implements Subject {
    @Override
    public void addFans(Observer fans) {
        fansWithEventListener.put(fans, null);
    }

    @Override
    public void deleteFans(Observer fans){
        fansWithEventListener.remove(fans);
    }

    /**
     * 记录每个对象的回调事件
     * 模拟了 c# eventhandler liuyifei.update += zhangsan.getinfobyemail //大话设计模式 14
     */
    private Map<Observer, String> fansWithEventListener =  new HashMap<>();

    /**
     * 通知所有的粉丝儿, 面条儿....
     */
    @Override
    public void notifyFans() {
        for (Observer fans : fansWithEventListener.keySet()) {
            if(fansWithEventListener.get(fans) == null){
                //默认采用qq通知
                fans.getInfoByQQ();
            }else{
                //如果有自己注册的事件, 就采用指定的通知方式通知
                try {
                    fans.getClass().getDeclaredMethod(fansWithEventListener.get(fans)).invoke(fans) ;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void addFansWithEventListener(Observer fans, String event) {
        fansWithEventListener.put(fans, event);
    }

    /**
     * 女神的状态改变, 所有订阅者第一时间收到消息
     */
    @Override
    public void statusChange() {
        this.notifyFans();
    }
}
/**
     * 事件委托模型: 订阅的时候顺便制定通知的方式
     * 基础的观察者模式通知方式比较单一, 只能通过一条路径通知订阅者
     * 现在我们有微信, 有扣扣, 有邮箱, 我们需要自己指定通过什么渠道来订阅通知
     */
public interface Observer {
    
    //主题发生改变时的通知渠道
    void getInfoByQQ();

    //主题发生改变时使用微信通知
    void getInfoByWeiXin();

    //主题发生改变时使用邮件通知
    void getInfoByEMail();
}
public class ZhangSan implements Observer {
    @Override
    public void getInfoByQQ() {
        System.out.println("我是张三, QQ通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByWeiXin() {
        System.out.println("我是张三, 微信通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByEMail() {
        System.out.println("我是张三, 邮箱通知: 女神更新状态了!!");
    }
}
public class LiSi implements Observer {
    @Override
    public void getInfoByQQ() {
        System.out.println("我是李四,QQ通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByWeiXin() {
        System.out.println("我是李四,微信通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByEMail() {
        System.out.println("我是李四,邮箱通知: 女神更新状态了!!");
    }
}
/**
 * 王二麻子实现订阅接口就可以有获取新动态的能力
 */
public class WangerMaZi implements Observer {

    /**
     * 订阅了菲菲女神微博后, 女神发新状态通知王二麻子的渠道
     */
    @Override
    public void getInfoByQQ() {
        System.out.println("我是王二麻子, QQ通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByWeiXin() {
        System.out.println("我是王二麻子, 微信通知: 女神更新状态了!!");
    }

    @Override
    public void getInfoByEMail() {
        System.out.println("我是王二麻子, 邮箱通知: 女神更新状态了!!");
    }
}
public class TestEventHandler {
    /**
     * 女神刘亦菲更新微博状态后发生什么
     */
    @Test
    public void afterLiuyifeiUpdateWeibo(){
        Subject liuyifei = new LiuYiFei();

        Observer zhangSan = new ZhangSan();
        Observer liSi = new LiSi();
        Observer wangerMaZi = new WangerMaZi();

//        liuyifei.addListener(zhangSan, "微信通知");
//      liuyifei.addListener(lisiSan, "邮箱通知");
        //指定通知以后的回调方法
        liuyifei.addFansWithEventListener(zhangSan, "getInfoByWeiXin");
        liuyifei.addFansWithEventListener(wangerMaZi, "getInfoByEMail");
        liuyifei.addFans(liSi);

        liuyifei.statusChange();
    }
}

源码路径

https://github.com/offline7LY/designpattern/tree/master/observer

以上是关于观察者模式与事件委托的主要内容,如果未能解决你的问题,请参考以下文章

《C#零基础入门之百识百例》(七十八)委托事件实例练习3 -- 观察者模式

《大话设计模式》——读后感 老板回来了,我不知道?——观察者模式之事件委托

观察者设计模式 Vs 事件委托(java)

事件委托实现观察者模式

常用设计模式之观察者模式 + 事件委托

利用事件委托弥补观察者模式不足