欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蚂蚁课堂第5期-互联网架构-007:观察者模式

程序员文章站 2022-06-15 11:35:00
...

1 观察者模式应用场景

课程内容:
1、什么是观察者、观察者模式应用场景
2、观察者实现的思路有那些
3、基于Jdk自带观察者模式实现消息异步传输
4、基于SpringBoot项目实现观察者模式

什么是观察者模式
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。

观察者模式应用场景
Zookeeper事件通知节点、消息订阅通知、安卓开发事件注册、分布式配置中心

2 观察者模式类图原理

蚂蚁课堂第5期-互联网架构-007:观察者模式

抽象主题(被观察者):它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。
抽象观察者:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体主题(被观察者):在具体主题的内部状态改变时,向所有注册过的观察者发出通知。
具体观察者:实现抽象观察者角色的更新接口,一边使本身的状态与主题的状态相协调。

3 纯手写Java观察者模式

抽象观察者

public interface Observer {

    /**
     * 通知观察者消息
     * @param message
     */
    void update(String message);
}

抽象主题

public interface AbstractSubject {

    /**
     * 添加观察者 注册观察者
     *
     * @param observer
     */
    void addObserver(Observer observer);

    /**
     * 移除观察者
     *
     * @param observer
     */
    void removeObserver(Observer observer);

    /**
     * 通知消息
     *
     */
    void notifyObserver(String message);
}

具体主题

public class WeChatSubject implements AbstractSubject {

    // 如何存放这些主题
    private List<Observer> observerList = new ArrayList<>();

    @Override
    public void addObserver(Observer observer) {
        // 注册或添加观察者
        observerList.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObserver(String message) {
        System.out.println("开始设置微信群发消息:" + message);
        // 调用观察者通知方法
        for (int i = 0; i < observerList.size(); i++) {
            Observer observer = observerList.get(i);
            // 调用该方法通知 获取具体的消息 群发
            observer.update(message);
        }
    }
}

具体观察者

public class UserObserver implements Observer {

    private String name;

    public UserObserver(String name){
        this.name = name;
    }

    @Override
    public void update(String message) {
        System.out.println(name + "老师收到消息..");
    }
}

测试类

public class Test001 {
    public static void main(String[] args) {

        // 1.创建具体的主题
        AbstractSubject abstractSubject = new WeChatSubject();
        // 2.开始注册或者添加观察者
        abstractSubject.addObserver(new UserObserver("小薇"));
        abstractSubject.addObserver(new UserObserver("小敏"));
        // 3.群发消息
        abstractSubject.notifyObserver("蚂蚁课堂666..");
    }
}

运行结果
蚂蚁课堂第5期-互联网架构-007:观察者模式

4 JDK观察者模式源码分析

1.Observer(观察者)
蚂蚁课堂第5期-互联网架构-007:观察者模式
2.Observable(主题)追踪所有的观察者,并通知他们。
蚂蚁课堂第5期-互联网架构-007:观察者模式

5 使用JDK观察者群发消息

自定义主题

public class MessageObservable extends Observable {

    @Override
    public void notifyObservers(Object arg) {
        // 1.修改状态为可以群发
        setChanged();
        // 2.调用父类的notifyObservers 群发消息
        super.notifyObservers(arg);
    }
}

自定义观察者

public class SmsObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送短信提醒内容:" + arg);
    }
}
public class EmailObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送邮件提醒内容:" + arg);
    }
}
public class WechatObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("用户下单成功,发送微信提醒内容:" + arg);
    }
}

运行监听开始

public class TestJdkObserver {
    public static void main(String[] args) {
        // 1.创建具体的主题
        Observable observable = new MessageObservable();
        // 2.注册观察者
        observable.addObserver(new SmsObserver());
        observable.addObserver(new EmailObserver());
        observable.addObserver(new WechatObserver());
        // 3.群发消息
        observable.notifyObservers("恭喜您中奖!");
    }
}

测试结果:
蚂蚁课堂第5期-互联网架构-007:观察者模式

注意:实际开发中具体观察者中的方法要异步处理,要单独有线程去运行这段代码。

6 SpringBoot事件通知底层原理

Spring封装事件监听
Spring实现事件通知,底层是采用观察者模式封装的

下单消息事件 OrderMessageEvent

public class OrderMessageEvent extends ApplicationEvent {

    /**
     * 群发消息的内容
     */
    private JSONObject jsonObject;

    public OrderMessageEvent(Object source, JSONObject jsonObject) {
        super(source);
        this.jsonObject = jsonObject;
    }

    public JSONObject getJsonObject() {
        return jsonObject;
    }

    public void setJsonObject(JSONObject jsonObject) {
        this.jsonObject = jsonObject;
    }
}

事件监听者 EmailListener/SmsListener

@Component
public class EmailListener implements ApplicationListener<OrderMessageEvent> {
    @Override
    @Async
    public void onApplicationEvent(OrderMessageEvent event) {
        // 如何获取到当前容器下面所有的观察者? 通过反射机制获取ApplicationListener接口下面的子类
        System.out.println(Thread.currentThread().getName() + "开始发送邮件消息内容:" + event.getJsonObject().toString());
    }
}
@Component
public class SmsListener implements ApplicationListener<OrderMessageEvent> {
    @Override
    @Async
    public void onApplicationEvent(OrderMessageEvent event) {
        System.out.println(Thread.currentThread().getName() + "开始发送短信消息内容:" + event.getJsonObject().toString());

    }
}

控制层

@RestController
public class OrderController {

    @Autowired
    private ApplicationContext applicationContext;

    @RequestMapping("/sendMsg")
    public String sendMsg() {
        // 1.定义发送消息内容
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("email", "aaa@qq.com");
        jsonObject.put("phone", "15123456789");
        jsonObject.put("text", "恭喜您中奖!");
        OrderMessageEvent orderMessageEvent = new OrderMessageEvent(this, jsonObject);
        applicationContext.publishEvent(orderMessageEvent);
        return "success";

    }
}

启动类

@SpringBootApplication
@EnableAsync
public class AppObserver {
    public static void main(String[] args) {
        SpringApplication.run(AppObserver.class);
    }
}

运行结果
蚂蚁课堂第5期-互联网架构-007:观察者模式