关于实现 “监听者模式" 类似模式的一点理解

监视者模式,观察者模式,监听器模式,本质上都是一个东西,其简单实现类图如下:

上图是经典的push类型的观察者模式,Observer对象往往提供一个类似support(Event)类型的方法来表示当前Observer对什么类型的事件感兴趣,当Subject发生变化时,Subject对象会调用notify方法通知在其注册的所有Observer,实现方法是,遍历List<Observer>,如果Observer支持其变化,调用Observer相对应的update方法完成更新;

对于这一经典设计模式,有时候需要提出一些实践上的问题,比如Observer往往会提供类似support(Event)的方法,当然也可不提供,代表当前Observer对Subject所有变化都会作出反应;当需要对某种特定Event进行支持的时候,就可以在support(Event)对Event类型进行判定,这往往取决于能将Subject的变化抽象为Event(往往是生命周期事件,如InitEvent,StartEvent,或者特定类别Event,如ApplicationEvent,BeanEvent等等),但当变化抽象不成Event(本质就是将变化,或者特征抽象,不一定非得是Event),此时将会出现这么一种状况,高层定义Observer时类似support方法将会出现好几个,而底层实现却只需实现一个或几个,并不需要全部实现,为了在编译期尽量给予支持,怎么办呢?

具体例子是:最近在研究spring源码并写复刻时,在PostProcessor(非典型的监听者模式)设计时出现这样的问题,当时在想这个Processor要么对bean的名字感兴趣(如容器进行初始化时,对定义的datasource初始化时需要进行额外的日志记录),这种需求是很常见的,因此会有一个support(String)方法,又有可能对某种类型的bean感兴趣,比如当是intercptor(spring mvc中的拦截器)类型的bean建立时你可能想记录下intercptor类型的bean的数量,于是给了个support(Class)方法,而底层Processor实现却只需要实现其中一个(当然可能都实现或者都不实现,具体细节不在讨论范围之内,只求表达顺畅),由于当前java接口中的方法必须全部实现,这有点不符合正常逻辑,当然你可能说参数类型使用Object,问题是解决了,但是Object类型会给client造成误解,对于一个Object类型的参数,如果没有很好的文档说明怎么处理,往往都是一头雾水,这也是个不好的习惯,参数使用Object,定义过高!或者你考虑对你想实现的support方法中加入处理逻辑,不想实现的support统统返回false(通常此类型的方法都是Boolean的返回值,但这无关紧要,只要返回一个代表 不行 的常数值就ok),但这其实并没有解决什么么问题,因为我们尽力想在编译期给予帮助,多出来的实现方法在IDE中仍有提示,仍旧会造成困惑,此时你要是在实现类的命名上有考虑,比如在这个例子中可以用BeanNameCheckedProcessor,BeanClassCheckedProcessor来表意,这也不失为一种解决方案。,或许,client不关心底层怎么实现的,人家又不查你源码;

之前请教阿里大佬,他说一般使用配置文件去表达此类需求,其实当时我也没太明白过来,大体上将逻辑配置在配置文件中,实现上仍旧按照传统思路来就好,可以设置一个基类,然后去继承就行了,配置文件是关键,如果还是不太懂,请联系我2900250200 QQ ;此次主要是想写自己的一点发现:

从网上找资料时突然看见接口默认实现了,这个关键字,其实之前也有过了解,当时不知道具体使用场景,现在说下:接口默认实现是java8的功能,一些基于老版的系统可能不能使用(我觉得java6的很少了吧),对于之前的例子可以这样做:

public interface Processor {

    default void interested(String beanName){}
    default void interested(Class<?> beanClass){}
    default void interested(Object o){}

    
    void process();
}

高层default给一个空实现

然后具体代码中

public class BeanNameProcessor implements Processor{

    @Override
    public void interested(String beanName) {
        // some check algorithm
    }

    @Override
    public void process() {

    }
}

这样就解决了问题;后台判断时可以用反射遍历实现的Processor接口所有方法,看是否重写了(检查@Override)的标志;

当然这样做依赖是否@Override标记,事实上你要是真不写这个注解编译也不会报错,但是因为这个 一是编程的习惯,不写@Override很多时候可能真会出错,二是你不写IDE会提示你,你直接实现接口的时候IDE会自动帮你加,所以此做法也是可以的,如若不放心可以将默认实现都返回否定意义的常量值

两种实现方式各有利弊(私以为接口默认实现方式更好一些)

如有细节需要讨论请联系我 2900250200 QQ

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值