工作中用到的观察者模式

in 软件设计模式 with 1 comment

i'm watching you
you are watching me

不知道为什么想到这句歌词,哈哈。

背景

公司需求是这样子的,开始抽象比喻,有一个吃饭操作,然后三个干饭人一起造,有的人喜欢用筷子吃,有的人喜欢有勺子吃,有的人喜欢拿盆干。
image20210801185315476.png

抽象一手

情况就是这么个情况。在业务中去“买生米”这个操作,是通过定时任务定期去别人系统去爬。“接水”这个操作,用户随时可能会提交,也就是,如果现在先“买了生米”后“接到水”,或者先“接到水”,后“买到生米”了,这个时候就要准备“煮成熟饭”了,接着干饭人就可以干饭了。

第一版逻辑

image20210801194700486.png

简单点说,用户定时任务开始了,就开始去扫数据库之前用户提交的数据,然后处理。功能可以实现。

但是我有点不爽

可能存在的问题

  1. 所有的判断干饭操作都给定时任务的那个方法处理,“干饭操作”和定时任务粘在了一起,看着烦。
  2. 如果在定时任务执行前,用户提交的数据积压太多,难说。

第二版逻辑

image20210801193150242.png

诶,找理由把干饭操作的代码封装了;接着在用户提交的数据时候,也去判断“干饭人”去不去干饭。一般满意。

但是经过前面工作发生的一些幺蛾子事,需求一直变动,万一又来了个干饭达人或者其他数据来源,代码改动挺大的。

所以,针对以上,我想到了观察者模式。

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

简单的说,就是小孩饿了就开始哭,然后家长听见就对小孩哭做出不同的反应。嗯差不多,如果比喻不形象那就当没看见这句话。

实现过程

JAVA 中已经有了对观察者模式的支持类。

被观察者 java.util.Observable
观察者 java.util.Observer

被观察者

@Service("watched")
public class Watched extends Observable {
    // 改变的数据
    private Map<String, String> watchedMap;

    Map<String, String> getWatchedMap() {
        return watchedMap;
    }

    public void setRepayMap(Map<String, String> watchedMap) {
        this.watchedMap = watchedMap;
        // 发送通知
        setChanged();
        notifyObservers();
    }
}

观察者

@Component
public class OneWatcher implements Observer {
    @Autowired
    public OneWatcher(Observable watched) {
        // 观察被观察者
        watched.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
        // 对map操作 实际场景需要开线程处理
        Map<String, String> watchedMap = ((Watched) o).getWatchedMap();
        System.out.println("我是一号干饭人,我用筷子干饭");
    }
}

@Component
public class TwoWatcher implements Observer {
    @Autowired
    public TwoWatcher(Observable watched) {
        // 观察被观察者
        watched.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
        // 对map操作 实际场景需要开线程处理
        Map<String, String> watchedMap = ((Watched) o).getWatchedMap();
        System.out.println("我是二号干饭人,我用勺子干饭");
    }
}

@Component
public class ThreeWatcher implements Observer {
    @Autowired
    public ThreeWatcher(Observable watched) {
        // 观察被观察者
        watched.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
        // 对map操作 实际场景需要开线程处理
        Map<String, String> watchedMap = ((Watched) o).getWatchedMap();
        System.out.println("我是三号干饭人,我用盆干饭");
    }
}

运行结果

image20210801213045320.png

观察者模式流程图

image20210801215220548.png

开闭原则

观察者模式符合开闭原则,复习下开闭原则。对内修改关闭,对外扩展开放。

每个观察者代码写好后,只要业务需求不变,那观察者代码都不需要修改,假设现在来了第四个干饭达人,同其他干饭人一样,按照观察者代码的模版,实现Observer接口,就可以加入一个新的干饭人了。就很丝滑的那种。