原文网址:Java设计模式系列--观察者模式写法2:JDK_IT利刃出鞘的博客-CSDN博客
简介
说明
本文用示例介绍观察者模式的一种写法:JDK。
JDK的观察者模式简介
在 Java 中,java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现这两个接口就可以编写观察者模式。
1. Observable
Observable 类是抽象目标类(被观察者),它有一个 Vector 集合成员变量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法。
- void addObserver(Observer o) 方法:用于将新的观察者对象添加到集合中。
- void notifyObservers(Object arg) 方法:调用集合中的所有观察者对象的 update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
- void setChange() 方法:用来设置一个 boolean 类型的内部标志,注明目标对象发生了变化。当它为true时,notifyObservers() 才会通知观察者。
2. Observer
Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 update 方法,进行相应的工作。
实例
本处使用一个贴近真实场景的案例:订单取消时,要有一系列操作,比如:账户业务需要给用户退钱、库存业务需要给商品退回数量。
在这个场景中,取消订单就是被观察者,账户业务和库存业务是观察者。
项目结构
业务数据类
取消订单时,主题会将这个数据给到感兴趣的观察者。
package com.knife.designPattern.jdk.bo;
import lombok.Data;
@Data
public class CancelOrderBO {
private String orderNo;
}
主题
package com.knife.designPattern.jdk.subject;
import com.knife.designPattern.jdk.bo.CancelOrderBO;
import java.util.Observable;
public class CancelOrderSubject extends Observable {
public void process(CancelOrderBO cancelOrderBO) {
super.setChanged(); //changed = true
super.notifyObservers(cancelOrderBO);
}
}
观察者
账户业务观察者
package com.knife.designPattern.jdk.observer;
import java.util.Observable;
import java.util.Observer;
/**
* 具体观察者: 账户业务
*/
public class AccountCancelOrderObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("账户业务开始处理订单取消。接收到的消息:" + arg);
}
}
仓库业务观察者
package com.knife.designPattern.jdk.observer;
import java.util.Observable;
import java.util.Observer;
/**
* 具体观察者: 库存业务
*/
public class StorageCancelOrderObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("库存业务开始处理订单取消。接收到的消息:" + arg);
}
}
主题持有者
只有主题还不行,需要有一个地方去调用它,添加一个主题持有者
package com.knife.designPattern.jdk.subject;
import com.knife.designPattern.jdk.bo.CancelOrderBO;
import com.knife.designPattern.jdk.observer.AccountCancelOrderObserver;
import com.knife.designPattern.jdk.observer.StorageCancelOrderObserver;
public class SubjectHolder {
private static final CancelOrderSubject instance = init();
private SubjectHolder() {
}
private static CancelOrderSubject init() {
// 创建被观察者
CancelOrderSubject orderCancelSubject = new CancelOrderSubject();
// 创建观察者
AccountCancelOrderObserver accountCancelOrderObserver =
new AccountCancelOrderObserver();
StorageCancelOrderObserver storageCancelOrderObserver =
new StorageCancelOrderObserver();
// 添加观察者,这样被观察者有数据时观察者就能感知到
orderCancelSubject.addObserver(accountCancelOrderObserver);
orderCancelSubject.addObserver(storageCancelOrderObserver);
return orderCancelSubject;
}
public static void process(CancelOrderBO cancelOrderBO) {
instance.process(cancelOrderBO);
}
}
测试
测试类
package com.knife.designPattern.jdk.controller;
import com.knife.designPattern.jdk.bo.CancelOrderBO;
import com.knife.designPattern.jdk.subject.SubjectHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "订单")
@RestController
@RequestMapping("order")
public class OrderController {
@ApiOperation("取消订单")
@PostMapping("cancel")
public String cancel(@RequestBody CancelOrderBO cancelOrderBO) {
SubjectHolder.process(cancelOrderBO);
return "success";
}
}
访问接口
启动项目后,访问Knife4j(接口文档)的地址:http://localhost:8080/doc.html
(当然,你用postman也完全可以)
结果
库存业务开始处理订单取消。接收到的消息:CancelOrderBO(orderNo=666)
账户业务开始处理订单取消。接收到的消息:CancelOrderBO(orderNo=666)