设计模式-观察者(Java实现)

314 阅读3分钟

前言

  • 从今天开始让我们一起每天学一个设计模式,我会从原理到代码实现到spring中怎么实现该设计模式

定义

  • 对象之间存在一对多或者一对一的依赖,当一个对象改变状态,依赖的对象就会收到通知并自动更新。MQ其实就属于一种观察者模式,发布者发布信息,订阅获取信息,订阅了就能收到信息,没订阅就收不到信息。

优点

  • 1.观察者和被观察这是抽象耦合的。
  • 2.建立一套触发机制。

缺点

  • 1.如果一个被观察这对象有很多的直接和间接的观察者的化,将所有的观察者都通知到会很话费时间。
  • 2.如果在观察和观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能导致系统崩溃。

代码实现

  • AbstrackInfo.java
public abstract class AbstrackInfo {

    //被监听的对象
    private Clock clock;

    abstract  void message();
}
  • EatInfo.java
public class EatInfo extends AbstrackInfo {

    @Override
    public void message(){
        System.out.println("大家吃饭了!");
    }
}
  • SleepInfo.java
public class SleepInfo extends AbstrackInfo{

    @Override
    public void message(){
        System.out.println("大家午睡了!");
    }
}
  • Clock.java
public class Clock {

    //一对多,需要接到通知的对象
    private List<AbstrackInfo> infos = new ArrayList<AbstrackInfo>();

    public void say(){
        System.out.println("上班了!");
        //通知
        update();
    }

    //添加要得到通知的对象
    public void addInfo(AbstrackInfo info){
        infos.add(info);
    }

    //通知
    public void update(){
        for (AbstrackInfo info : infos) {
            info.message();
        }
    }

    public static void main(String[] args) {
        Clock clock = new Clock();
        AbstrackInfo eat = new EatInfo();
        AbstrackInfo sp = new SleepInfo();

        clock.addInfo(eat);
        clock.addInfo(sp);

        clock.say();
    }
}

spring观察者模式

  • ApplicationContext事件机制是观察者设计模式实现的,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
  • 如果容器中有一个AppliListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将会自动被触发。这种事件机制都必须要程序显示的触发。
  • 其中spring有一些内置的时间,当完成某种操作时会发出某些事件动作,比如监听contextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该时间,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。
  • 同样时间可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。
  • 对象说明
    • 1.ApplicationContext容器对象
    • 2.ApplicationEvent事件对象(ContextRefreshedEvent容器刷新事件)
    • 3.ApplicationListener事件监听对象

ApplicationContext事件监听

  • 当ApplicationContext内的Bean对象初始化完成时,此时可以通过监听ContextRefreshedEvent得到通知。
  • 1.创建监听对象 ApplicationContextListener
    • ApplicationEventListener.java
public class ApplicationEventListener implements ApplicationListener<ContextRefreshedEvent> {

    //发生指定事件后会触发该方法执行
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext act = contextRefreshedEvent.getApplicationContext();
        System.out.println("监听到容器初始化完成!");

        //启动->从数据库加载对应的数据(省市区)->填充Redis

    }
}
  • 2.将对象添加到容器中
<bean id="applicationEventListener" class="com.itheima.spring.ApplicationEventListener"/>
  • 3.测试
    • SpringContextTest.java
public class 
SpringContextTest{

    public static void main(String[] args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("spring-event.xml");
    }
}

自定义监听事件

  • 自定义监听事件可以监听容器变化,同时也能精确定位指定事件对象
  • 定义事件监听对象MessageEventListener
public class MessageEventListener implements ApplicationListener {

    //监听触发执行
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        System.out.println("监听到了对应事件!");
    }
}
  • 定义事件对象: MessageEvent
public class MessageEvent extends ApplicationEvent {
    /***
     * 可以用于传递数据
     */
    public MessageEvent(Object source) {
        super(source);
    }
}
  • 将对象添加到容器中
<bean id="messageEventListener" class="com.itheima.spring.MessageEventListener"/>
  • 测试 SpringContextTest.java
public class SpringContextTest {

    public static void main(String[] args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("spring-event.xml");

        //添加一个自定义事件
        act.publishEvent(new MessageEvent("hello!"));
    }
}