精讲23种设计模式-005:基于观察者模式设计异步多渠道群发框架

1 观察者模式课程内容的引入

课程内容

  1. 观察者模式基本的observer概念
  2. 观察者模式在实际开发中的应用场景
  3. 如何基于观察者模式设计多渠道群发框架
  4. ApplicationListener事件监听原理

2 观察者模式介绍

观察者基本概念
当一个对象发生改变的时候可以通知给其他所有的对象

观察者应用场景

  1. zk临时节点监听(当zk临时节点发生变化,会通知给所有客户端)
  2. 分布式配置中心 nacos、config、携程Apollo刷新配置文件
  3. 多渠道群发
    addOrder(){
    // 1.向数据库中插入订单数据
    // 2.发送短信代码
    // 3.发送邮件代码
    // 4.发送微信代码
    }
    ==》观察者模式一行代码封装

3 观察者模式类图结构的分析

请添加图片描述

4 定义观察者模式的接口

public interface Observer {

    void sendMsg(JSONObject jsonObject);
}
@Component
@Slf4j
public class SmsObserver implements Observer {

    @Override
    public void sendMsg(JSONObject jsonObject) {
        log.info("使用观察者发送短信");
    }
}
@Component
@Slf4j
public class EmailObserver implements Observer {
    @Override
    public void sendMsg(JSONObject jsonObject) {
        log.info("使用观察者发送邮件");
    }
}
@Component
public class MayiktSubject {

    private List<Observer> listObserver = new ArrayList<>();
    private ExecutorService executorService;

    public MayiktSubject() {
        executorService = Executors.newFixedThreadPool(10);
    }

    /**
     * 新增Observer
     *
     * @param Observer
     */
    public void addObserver(Observer Observer) {
        listObserver.add(Observer);
    }

    /**
     * 通知给所有观察者
     *
     * @param jsonObject
     */
    public void notifyObServer(JSONObject jsonObject) {
        for (Observer obServer : listObserver) {
            // 单独开启线程异步通知
            executorService.execute(() -> obServer.sendMsg(jsonObject));
        }
    }

}

5 项目启动注册读观察者(自动注册)

@Component
public class StartService implements ApplicationRunner, ApplicationContextAware {

    @Autowired
    private SmsObserver smsObserver;
    @Autowired
    private EmailObserver emailObserver;
    @Autowired
    private MayiktSubject mayiktSubject;

    private ApplicationContext applicationContext;

    // 当SpringBoot启动成功之后,再注册SmsObserver和EmailObserver
    @Override
    public void run(ApplicationArguments args) throws Exception {
//        mayiktSubject.addObserver(smsObserver);
//        mayiktSubject.addObserver(emailObserver);
        // 使用java反射机制获取Observer下所有子类自动注册到集合中
        /**
         * 自动注册观察者
         * 1. 使用Spring获取该Observer下有哪些bean对象
         * 2. 直接添加到集合中
         */
        // 根据接口类型返回相应的所有bean
        Map<String, Observer> map = applicationContext.getBeansOfType(Observer.class);
        for (String key : map.keySet()) {
            Observer Observer = map.get(key);
            mayiktSubject.addObserver(Observer);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

6 测试手写观察者模式

@RestController
@Slf4j
public class OrderService {

    @Autowired
    private MayiktSubject mayiktSubject;

    @RequestMapping("/addOrder")
    public String addOrder() {
        log.info("1.调用数据库下单订单代码:");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sms", "1865891111");
        jsonObject.put("email", "644064779@qq.com");
        mayiktSubject.notifyObServer(jsonObject);
        return "success";
    }

}

运行结果:
请添加图片描述

7 使用Spring事件监听实现观察者

定义消息实体类

@Data
public class UserMessageEntity extends ApplicationEvent {

    private String email;
    private String phone;
    private String userId;

    public UserMessageEntity(Object source) {
        super(source);
    }

    public UserMessageEntity(Object source, String email, String phone) {
        super(source);
        this.email = email;
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "email:" + email + ",phone:" + phone;
    }
}

定义事件通知

@Component
@Slf4j
public class EmailListener implements ApplicationListener<UserMessageEntity> {

    /**
     * 监听的方法
     *
     * @param event
     */
    @Override
    public void onApplicationEvent(UserMessageEntity event) {
        log.info("使用SpringBoot观察者发送邮件:" + event.getEmail());
    }
}
@Component
@Slf4j
public class SmsListener implements ApplicationListener<UserMessageEntity> {

    /**
     * 监听的方法
     *
     * @param event
     */
    @Override
    public void onApplicationEvent(UserMessageEntity event) {
        log.info("使用SpringBoot观察者发送短信:" + event.getPhone());

    }
}

发布事件

@RestController
@Slf4j
public class OrderService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @RequestMapping("/addOrder2")
    public String addOrder2() {
        log.info("1.调用数据库下单订单代码:");
        UserMessageEntity userMessageEntity = new UserMessageEntity(this, "644064779@qq.com", "1865891111");
        applicationEventPublisher.publishEvent(userMessageEntity);
        return "success";
    }

}

运行结果:
请添加图片描述
源码下载地址(mayikt_designPattern_5.zip):
链接:https://pan.baidu.com/s/1wWKZN1MbXICZVW1Vxtwe6A
提取码:fire

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值