设计模式:观察者模式和监听器模式

最近有个需求,大概是想用一下观察者模式/或者是监听器模式,来实现一下。那问题来了什么是观察者模式,什么是监听器模式?两者之间有哪些联系和不同。具体实现是什么样的,那就听我讲解一下。

观察者模式和监听器模式的组成

首先做一个总结,监听器模式实际上是在观察者模式的基础上进一步的封装。

首先是观察者模式,观察者模式分为两部分,观察者Observer和被观察者。观察者根据被观察者作为事件源,当执行逻辑涉及到触发逻辑,调用观察者的相关逻辑。

监听器相对来说多了个事件event,根据事件去监听。相当于是三部分EventSource事件源(有的地方也叫做register注册中心),Event事件(创建事件调动监听逻辑),Listener(监听器);

我这里借了一个别人的图:

设计模式:观察者模式和监听器模式_第1张图片

观察者和监听器的具体实现

代码的地址我放在我的github上:

girhub:monitor和observer对应的实现,监听器那个模式由于是接口不是抽象类,可能有的idea会报错,但是可以执行,有时间我再修改一版

观察者:对应的是两部分Subject和Observer,一个是主体,观察者类似订阅者一样去订阅自己的主题。

被观察者或者说是主题的接口以及它的实现类

package com.example.test.observer;

import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 * @Desc:subject 被观察者(主题发布的主题)
 */
public interface Subject {

    /**
     * 添加观察者
     * @return
     */
    public List addObserver(Observer observer);

    /**
     * 删除某个观察者
     * @param observer
     * @return
     */
//    public List removeObserve(Observer observer);

    /**
     * 发送消息/主题,让观察者动起来
     */
    public void sendSubjectToObserver();


}

被观察者实现类

package com.example.test.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class SubjectImpl implements Subject{

    List list;

    @Override
    public List addObserver(Observer observer) {
        if(list == null){
            list = new ArrayList<>();
        }
        list.add(observer);
        return list;
    }

    @Override
    public void sendSubjectToObserver() {
         for(Observer observer : list){
              observer.sendSubject();
         }
    }
}

注意里面的几个方法,后面对比监听者也用的到。

观察者抽象类:之所以是抽象类是方便扩展实现不同类型的观察者

package com.example.test.observer;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public abstract class Observer {
    public abstract void sendSubject();
}

观察者A实例

package com.example.test.observer;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class ObserverA extends Observer{
    @Override
    public void sendSubject() {
        System.out.println("我是观察者A");
    }
}

我们观察一下观察者,觉得只分成两部分,能不能做个扩展对应触发观察者逻辑的部分能不能拿出来,这样迄不是扩展性更强。

当然可以监听器,就是单独出来一个事件,观察者根据事件的创建直接出发逻辑,看起来好像是在监听一样,听到消息就要去报告一样.

以下是监听器的代码

监听器的事件源,它对应的是观察者的被观察者的一部分,包括注册,维护观察者/监听器列表等。

package com.example.test.monitor;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 * 对比观察者的的被观察者/主题。这个角色进行对比
 */
public class EventSource {

    /**
     * 监听器列表
     */
    private List listeners;

    /**
     * 添加监听器
     * @param myMonitor
     * @return
     */
    public List addMonitor(MyMonitor myMonitor){
        if( listeners == null ){
            listeners = new ArrayList<>();
        }
        listeners.add(myMonitor);
        return listeners;
    }

    /**
     * 移除监听器
     * @return
     */
    public List removeMonitor(){
        if(listeners == null){
            return listeners;
        }
        for (MyMonitor listener : listeners){

            if(listeners.getClass().isInstance(DiguaMonitor.class)){
                listeners.remove(listener);
            }
            if(listener.getClass().isInstance(QieziMonitor.class)){
                listeners.remove(listener);
            }

        }
        return listeners;
    }


    public void gotoListener(Event event){
        for(MyMonitor listener : listeners){
            listener.monitotToTudou(event);
        }
    }
}

事件,其实可以看作是一个抽象出来的监视对象,当监视对象创建出来就会,有对应的监视器采取相关的动作,这里我用的是,“地瓜,地瓜,我是土豆,我听到了!”,这种耳熟能详的暗号来做例子,地瓜可以监视土豆,是不是茄子也可以,这是当然的。

以下是监视器的代码:

package com.example.test.monitor;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class DiguaMonitor implements MyMonitor{
    @Override
    public void monitotToTudou(Event event) {

       if(event.getType() == 1){
           System.out.println("地瓜,地瓜,我是土豆,我听到了!");
       }

    }
}

那现在我们缺一个被监视的土豆对象,这个被监视的对象就是我们的Event事件

package com.example.test.monitor;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/4/29
 */
public class Event {

    /**
     * 类型:1 代表地瓜是监听者要监听的事件 ,2 代表茄子是监听者且子要监听的时间
     */
    private Integer type;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }
}

spring的监视器

spring也是自带监视器,不管是注解@EventListener还是实现ApplicationListener接口,实际都是你去继承实现人家定的模式。

当然他们刚开始是有区别的,有的是后置处理器处理的,有的是直接接口的实现类,但最后的去处都是spring的多播放器然后再到applicationListeners管理雕鹰设计模式:观察者模式和监听器模式_第2张图片
这里面推荐一个小哥的专栏,我也是从这里对spring的两种监听器有了更深一步的了解。

涉及到spring的源码的spring监听器解析

你可能感兴趣的:(代码整洁之道,算法,spring,设计模式,观察者模式,intellij-idea)