JAVA设计模式—观察者模式Observer的演变
前言
观察者模式其实没啥,就是把方法调用 ,用多态抽象封装了一下。
调用方称为观察者,被调用方是被观察者。
和MQ非常类似 不过MQ是异步的 这个同步的
观察者模式基础
以下是小孩(被观察者)哭这个动作,通知所观察者(Mum Dad Dog)做出不同的反应
/** * 分离观察者与被观察者 */ class Child { private boolean cry = false; private List<Observer> observers = new ArrayList<>(); { observers.add(new Dad()); observers.add(new Mum()); observers.add(new Dog()); } public boolean isCry() { return cry; } public void wakeUp() { cry = true; for(Observer o : observers) { o.actionOnWakeUp(); } } } /**定义主题对象接口 观察者接口**/ interface Observer { void actionOnWakeUp(); } class Dad implements Observer { public void feed() { System.out.println("dad feeding..."); } @Override public void actionOnWakeUp() { feed(); } } class Mum implements Observer { public void hug() { System.out.println("mum hugging..."); } @Override public void actionOnWakeUp() { hug(); } } class Dog implements Observer { public void wang() { System.out.println("dog wang..."); } @Override public void actionOnWakeUp() { wang(); } } public class Main { public static void main(String[] args) { Child c = new Child(); //do sth c.wakeUp(); } }
dad feeding...
dog wang...
mum hugging...
观察者模式本身比较简单 就是多态的应用
很多时候 观察者需要根据这件事的具体情况做出相应的处理:比如小孩哭的时间和地点,观察者做出的反应应该不同
下面对观察者模式进行进一步的封装
抽象出处理事件类
把小孩哭得所有状况传到一个事件里面
//事件类 fire Event class wakeUpEvent{ long timestamp; String loc; public wakeUpEvent(long timestamp, String loc) { this.timestamp = timestamp; this.loc = loc; } } interface Observer { void actionOnWakeUp(wakeUpEvent event); }
有点类似发布订阅,发布者发布一个事件,订阅者接收这个事件
事件类增加事件源对象,并形成继承体系
大多数时候,我们处理事件的时候,需要事件源对象(有时观察者需要事件原对象的一些资源)
class wakeUpEvent{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } }
因为我们都是面向接口编程 所以把事件定义一个接口或者抽象类。这也是多态的应用
abstract class Event<T> { abstract T getSource(); } class wakeUpEvent extends Event<Child>{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } @Override Child getSource() { return source; } }
其实Observer Listener Hook CallBack 这些都是观察者模式
最终代码
package com.mashibing.dp.observer.v8; import java.util.ArrayList; import java.util.List; /** * 有很多时候,观察者需要根据事件的具体情况来进行处理 * 大多数时候,我们处理事件的时候,需要事件源对象 * 事件也可以形成继承体系 */ class Child { private boolean cry = false; private List<Observer> observers = new ArrayList<>(); { observers.add(new Dad()); observers.add(new Mum()); observers.add(new Dog()); observers.add((e)->{ System.out.println("ppp"); }); //hook callback function } public boolean isCry() { return cry; } public void wakeUp() { cry = true; wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed", this); for(Observer o : observers) { o.actionOnWakeUp(event); } } } abstract class Event<T> { abstract T getSource(); } class wakeUpEvent extends Event<Child>{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } @Override Child getSource() { return source; } } interface Observer { void actionOnWakeUp(wakeUpEvent event); } class Dad implements Observer { public void feed() { System.out.println("dad feeding..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { feed(); } } class Mum implements Observer { public void hug() { System.out.println("mum hugging..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { hug(); } } class Dog implements Observer { public void wang() { System.out.println("dog wang..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { wang(); } } public class Main { public static void main(String[] args) { Child c = new Child(); //do sth c.wakeUp(); } }
ApplicationListener
Spring中的ApplicationListener也是使用的观察者模式,下面两种方式做比较
https://www.cnblogs.com/ssskkk/p/12942375.html#_label4
附言:
公司有个制单系统,主要是制单和审单,
从一开始的方法调用优化成Spring的事件驱动(事件驱动 就是把方法调用的调用者和被调用者分离封装了一下)
当时把单子封装成事件Event,每次来单和审单都会构造一个Event,然后publishEvent出去
制单人和审核人对单子的操作封装成 一个个的观察者Listener