观察者模式
什么是观察者模式
当一个对象,发生改变的时候,通知给其他对象
在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。 其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。
观察者模式应用场景
Zookeeper事件通知节点、消息订阅通知、 分布式配置中心
观察者模式原理类图
抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。 Subject ObServer
伪代码通过观察者实现发送短信和 发送邮件<原生>
定义 抽象观察者
代码语言:javascript复制/**
* 抽象观察者
*/
public interface ObServer {
void sendObServer(JSONObject jsonObject);
}
具体实现
代码语言:javascript复制@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");
}
}
所有观察者的容器
代码语言:javascript复制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
代码语言:javascript复制@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
代码语言:javascript复制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;
}
}
具体实现
代码语言:javascript复制@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");
}
}