观察者模式

什么是观察者模式

当一个对象,发生改变的时候,通知给其他对象

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

观察者模式应用场景

Zookeeper事件通知节点、消息订阅通知、
分布式配置中心

观察者模式原理类图

1654668377980
抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。

具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
Subject ObServer

伪代码通过观察者实现发送短信和 发送邮件<原生>

定义 抽象观察者


/**
 * 抽象观察者
 */
public interface ObServer {
    void sendObServer(JSONObject jsonObject);
}
具体实现
@Component
@Slf4j
public class EmailObServer implements ObServer{
    @Override
    public void sendObServer(JSONObject jsonObject) {
     log.info("发生成功  EmailObServer");
    }
}
@Component
@Slf4j
public class SMSObServer implements ObServer{
    @Override
    public void sendObServer(JSONObject jsonObject) {
        log.info("发生成功  SMSObServer");
    }
}
所有观察者的容器
public class Subject {
    private List<ObServer> obServerList=new ArrayList<>();
    private ExecutorService executorService;

    /**
     * 新增 obServer
     * @param obServer
     */
    public void  addObServer(ObServer obServer){
        obServerList.add(obServer);
    }

    /**
     * 通知给所有的观察者
     * @param jsonObject
     */
    public void notifyObServer(JSONObject jsonObject){
      for (ObServer obServer : obServerList) {
          executorService.execute(new Runnable() {
              @Override
              public void run() {
                  obServer.sendObServer(jsonObject);
              }
          });
      }
    }
}
在项目完全启动后,在注册到subject
@Component
@Slf4j
public class StartService implements ApplicationRunner, ApplicationContextAware {
    @Autowired
    private SMSObServer sMSObServer;
    @Autowired
    private EmailObServer emailObServer;
    @Autowired
    private Subject subject;

    private ApplicationContext applicationContext;

    /**
     * 当项目启动成功以后,再将 我们的observer注册到容器里面去
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("注册成功");
        //使用java的反射机制获取observer 下所有的子类注册到集合中。
        /**
         * 1。使用spring ioc获取bean对象
         * 2。添加到集合中
         */
        Map<String, ObServer> beansOfType = applicationContext.getBeansOfType(ObServer.class);
        beansOfType.forEach((k,v)->{
            subject.addObServer(v);
            log.info("注册成功"+k+"   "+v);
        });
    }

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

伪代码通过观察者实现发送短信和 发送邮件 spring

定义实体类 必须继承ApplicationEvent

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, String userId) {
        super(source);
        this.email = email;
        this.phone = phone;
        this.userId = userId;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
}

具体实现

@Component
@Slf4j
public class EmaiListerner implements ApplicationListener<UserMessageEntity> {
    /**
     * 监听方法
     * @param userMessageEntity
     */
    @Override
    public void onApplicationEvent(UserMessageEntity userMessageEntity) {
        log.info("EmaiListerner");
    }
}
@Component
@Slf4j
public class SmsListener implements ApplicationListener<UserMessageEntity> {
    /**
     * 监听方法
     * @param userMessageEntity
     */
    @Override
    public void onApplicationEvent(UserMessageEntity userMessageEntity) {
        log.info("SmsListener");
    }
}

问题,spring是同步通知执行的。