SpringBoot深度探究(五)JDK观察者模式探究

56 篇文章 3 订阅
12 篇文章 2 订阅

前言

上一篇博客【观察者设计模式的演进】详细的讲解了观察者模式的概念以及如何从零开始实现一个观察者模式,那么这一篇的主要内容就是JDK中观察者设计模式的实现。通过对比观察者模式,JDK观察者模式,以及Spring对观察者模式的应用去研究SpringBoot中的事件编程模型是怎样的一个过程。更多Spring内容进入【Spring解读系列目录】

场景回顾

上一篇做了一个小场景去实施观察者模式,再回顾一下:假设一个花盆里有一朵花(Flower),花朵的旁边有两个测试人员小红(XiaoHong)和李华(Lihua)。当这朵花开放(bloom)的时候小红会开心的笑(laugh),但是李华会因为花粉过敏而流泪(tear)。继续用这个场景来做JDK的观察者模式实现。

Observer观察者

在进一步实现之前,需要先了解一下Observer接口是什么样子的。

public interface Observer {
    void update(Observable o, Object arg);
}

可以看到,Observer接口里面只有一个update()方法,和上个例子创建的FlowerListener异曲同工。只不过我们自己起的名字叫做action()。进一步解析一下参数Observable o,这个参数就是被观察者,也就是我们创建的Flower类,只不过在我们自己的例子中,为了细化动作又封装了一个FlowerEvent类。

Observable被观察者

既然上面类比了我们自己的Flower类,那么就进入这个类中看下里面的方法。

public class Observable {
   private boolean changed = false;
   private Vector<Observer> obs;//使用集合,我们的例子使用的是List
   //实例化的时候创建Vector
   public Observable() {
      obs = new Vector<>();
   }
   //可以自由增加观察者
   public synchronized void addObserver(Observer o) {
      if (o == null)
         throw new NullPointerException();
      if (!obs.contains(o)) {
         obs.addElement(o);
      }
   }
   //可以自由删除观察者
   public synchronized void deleteObserver(Observer o) {
      obs.removeElement(o);
   }
   //通知观察者
   public void notifyObservers() {
      notifyObservers(null);
   }
   //通知观察者
   public void notifyObservers(Object arg) {
      Object[] arrLocal;
      synchronized (this) {
         if (!changed)
            return;
         arrLocal = obs.toArray();
         clearChanged();
      }
      for (int i = arrLocal.length-1; i>=0; i--)
         ((Observer)arrLocal[i]).update(this, arg);
   }
   //可以批量删除观察者
   public synchronized void deleteObservers() {
      obs.removeAllElements();
   }
   //可以修改状态
   protected synchronized void setChanged() {
      changed = true;
   }
   //可以重置状态
   protected synchronized void clearChanged() {
      changed = false;
   }
   //可以获取状态
   public synchronized boolean hasChanged() {
      return changed;
   }
   //可以计算观察者的数量
   public synchronized int countObservers() {
      return obs.size();
   }
}

其实可以看到这个类就是上篇例子中Flower的超级增强版。涵盖了被观察者的一切特性:对观察者的增减,对标识变量的修改重置获取,通知观察者,甚至还有计算观察者数量的方法。相比之下Flower类里只有一个寒酸的增加,不过既然是模仿,做到精髓就也够了。

实现场景

了解完了这些源码内容以后,故事场景实现就很好做了。这个例子中应该有两个观察者LiHuaJDK和XiaoHongJDK会对同一个事件做不同的反应。然后根据Observable封装一个FlowerEventJDK用来通知观察者花开了的动作。

LiHuaJDK类:

public class LiHuaJDK implements Observer {
    /**
     * 实现update方法,对比的就是上篇帖子中我们自己创建的action方法,也就是响应方法
     *   其中Observable o就是被观察者,也就是上个例子中的Flower.
     */
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("这里是李华,看到花应该流泪");
    }
}

XiaoHongJDK类:

public class XiaoHongJDK implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("这里是小红,看到花应该笑");
    }
}

FlowerEventJDK类:

public class FlowerEventJDK extends Observable {
    public void bloomNow(){
       setChanged(); //改变标识
        notifyObservers(); //通知观察者
    }
}

测试类:

public class TestJDK {
    public static void main(String[] args) {
        FlowerEventJDK flowerJDK=new FlowerEventJDK();
        flowerJDK.addObserver(new LiHuaJDK());
        flowerJDK.addObserver(new XiaoHongJDK());
        flowerJDK.bloomNow();
    }
}
打印结果
这里是小红,看到花应该笑
这里是李华,看到花应该流泪

通过上面的例子,使用JDK提供的观察者模型就实现了对这个场景的模拟。

观察者模式的优势

说了这么多观察者模式的实现和概念,再进一步梳理SpringBoot的事件编程模型之前不妨先捋清楚这样设计的好处。毕竟这个世界就是无利不起早的运作模式。

首先看到除了可以自由的进行增加删除观察者以外,JDK编程模式还可以直接通过外部继承的方式直接操作通知和标识的修改。也就是说当一个事件不需要被监听的时候,只需要取消改变的动作,或者取消通知观察者这个动作就可以了,而观察者可以说是无感知的。可以说是一个强解耦的设计。

如果我们有这样一个例子。从购买到生成订单,假如中间要经过打折,短信通知用户等等一系列的动作以后再入库,那么其中任何一个环节出问题,订单就无法入库。这样显然是不合理的,因为打折和通知是否完成和订单没有任何关系。如果有一天打折功能要修改,或者通知功能从短信变成了邮件,对整个系统的改动就非常的大。

在这里插入图片描述

但是如果我们引入观察者模式基于事件变成会变成什么样呢。首先基于事件的话,只要订单生成直接入库,至于打折和通知用户完全是分支事件。而且如果前面做了持久化,那么这一系列的分支事件就算是失败了依然有补救的机会。那么按照观察者事件模式修改一下这个逻辑。

在这里插入图片描述

修改以后可以看到打折和通知两部分已经和主逻辑进行了一个解耦。当监听的事件不再需要的时候直接去掉监听,或者去掉通知即可,主逻辑完全不需要任何修改,从而保证了主链的封闭。而且订单的生成只是通知后续的事件,而不是去影响下一步操作。

总结

通过上面的分析,可以知道观察者的设计模式可以使得:观察者增加或者删除无需修改被观察者的代码,只需要调用被观察者的增加或者删除方法即可;被观察者只负责通知观察者,但是无需了解观察者如何处理通知;观察者方面只需要等待被观察者的通知,无需知道被观察者动作的细节。再详细了解了观察者模式之后,就可以进入Spring的事件变成模型的解析了,下一篇【Spring事件编程模型(Listener-Event)的扩展】就会详细的讲解一下SpringBoot事件编程模型的扩展与应用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值