观察者设计模式
观察者设计模式的介绍
观察者设计模式是一种行为型设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件处理系统或者需要实现发布-订阅机制的情况下。
在观察者模式中,有两类主要角色:
Subject(主题):也称为被观察者,它维护一组依赖于它的观察者对象,并在自身状态发生变化时通知这些观察者。
Observer(观察者):观察者订阅主题的变化,当主题的状态发生变化时,观察者会收到相应的通知,并执行相应的操作。
典型的观察者模式实现包括:
注册和移除观察者:主题对象可以允许观察者订阅或取消订阅。
通知观察者:当主题对象状态发生变化时,通知所有注册的观察者。
更新观察者状态:观察者接收到通知后,执行相应的操作以更新自身状态。
项目应用背景
在一个工作流管理系统中,在子节点开启前,结束前结束后都会触发特定的方法。当只有一个业务单据的时候可以直接在监听类Listener中增添特定的执行逻辑。但是当业务单据多时,每一个单据在增加执行逻辑都需要修改监听类,该监听类耦合性性增加,不便于阅读跟后续的修改。
引入观察者设计模式
- 代码可读性和可维护性:
使用观察者设计模式可以将代码分解为更小的、更具可管理性的模块,主题对象和观察者对象之间的职责清晰分离。这种分离使得代码更易于理解和维护,每个类都只需关注自己的特定任务,而不必关心其他类的实现细节。
通过将观察者对象的具体逻辑封装在单独的类中,使得代码更具可读性。开发人员可以更轻松地理解每个观察者对象所负责的功能,从而更容易调试和修改代码。 - 代码复用性和可扩展性:
观察者设计模式提高了代码的复用性。由于主题对象和观察者对象之间的松耦合关系,可以轻松地添加新的观察者对象而无需修改主题对象的代码。这样一来,系统具有更高的可扩展性,可以根据需要动态地添加或删除观察者对象,而不会影响到其他部分的代码。
观察者模式还支持多播机制,一个主题对象的状态变化可以同时通知多个观察者对象。这种机制使得系统更具灵活性,能够满足不同场景下的需求,而无需大规模修改现有代码。 - 系统的解耦和降低复杂性:
观察者设计模式将主题对象和观察者对象解耦,使得它们之间的依赖关系降低到最低限度。主题对象不需要了解观察者对象的具体实现,只需要维护一个观察者列表,并在状态变化时通知这些观察者即可。这种解耦有助于降低系统的复杂性,使得系统更易于理解和维护。
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这段Java代码实现了提供的UML图中的观察者设计模式。主题类 ConcreteSubject 实现了主题接口 Subject,负责管理观察者对象并在状态变化时通知它们。观察者类 ConcreteObserver 实现了观察者接口 Observer,定义了具体的更新逻辑。
实际代码实现
下面展示代码逻辑 代码实现
。
public class BillWorkflowListener extends CommonWorkflowListener {
private final ObjectProvider<CustomBillWorkflowListener> customWorkflowListeners;
public XnkBillWorkflowListener(ObjectProvider<CustomBillWorkflowListener> listeners) {
this.customWorkflowListeners = listeners;
}
/**
* 提交前
*/
@Override
public void beforeProcessStart(WorkflowEvent event) {
super.beforeProcessStart(event);
performCustomListener("beforeProcessStart", event,
listener -> listener.beforeProcessStart(event));
}
/**
* 提交后
*/
@Override
public void afterProcessStart(WorkflowEvent event) {
super.afterProcessStart(event);
performCustomListener("afterProcessStart", event,
listener -> listener.afterProcessStart(event));
}
/**
* 流程终止(提交取回)
*/
@Override
public void afterProcessAbort(WorkflowEvent event) {
super.afterProcessAbort(event);
performCustomListener("afterProcessAbort", event,
listener -> listener.afterProcessAbort(event));
}
/**
* 流程节点动作
*/
@Override
public void onBeforeNodeLeft(WorkflowNodeEvent event) {
super.onBeforeNodeLeft(event);
performCustomListener("onBeforeNodeLeft", event,
listener -> listener.onBeforeNodeLeft(event));
}
/**
* 流程结束(通过)
*/
@Override
protected void onApproved(WorkflowEvent event, Bill bill) {
super.onApproved(event, bill);
performCustomListener("onApproved", event,
listener -> listener.onApproved(event, bill));
}
/**
* 流程结束(驳回)
*/
@Override
protected void onRejected(WorkflowEvent event, Bill bill) {
super.onRejected(event, bill);
performCustomListener("onRejected", event,
listener -> listener.onRejected(event, bill));
}
/**
* 当前节点触发,还没有开始做业务处理之前
*/
@Override
public void onBeforeNodeTriggered(WorkflowNodeEvent event) {
super.onBeforeNodeTriggered(event);
performCustomListener("onBeforeNodeTriggered", event,
listener -> listener.onBeforeNodeTriggered(event));
}
/**
* 当前节点触发,生成UserTask之后触发
*/
@Override
public void onAfterNodeTriggered(WorkflowNodeEvent event) {
super.onAfterNodeTriggered(event);
performCustomListener("onBeforeNodeLeft", event,
listener -> listener.onAfterNodeTriggered(event));
}
private void performCustomListener(String method, WorkflowEvent e, Consumer<CustomBillWorkflowListener> c) {
customWorkflowListeners.forEach(l -> {
if (l.supportByEvent(e)) {
log.info("Invoke method '{}', customBillWorkflowListener={}, workflowName={}, bizName={}, bizObjId={}",
method, l.getClass().getSimpleName(), e.getWorkflowName(), e.getBizName(), e.getBizObjId());
// Invoke method
c.accept(l);
}
// Skipp
else {
log.info("Skipped invoke method '{}', customBillWorkflowListener={}, workflowName={}, bizName={}, bizObjId={}",
method, l.getClass().getSimpleName(), e.getWorkflowName(), e.getBizName(), e.getBizObjId());
}
});
}
public interface CustomBillWorkflowListener extends Ordered {
@Override
default int getOrder() {
return LOWEST_PRECEDENCE;
}
/**
* 根据工作流事件确定此监听器是否支持
*
* @param event 工作流事件
*/
boolean supportByEvent(WorkflowEvent event);
/**
* 提交前
*/
default void beforeProcessStart(WorkflowEvent event) {
}
/**
* 提交后
*/
default void afterProcessStart(WorkflowEvent event) {
}
/**
* 流程终止(提交取回)
*/
default void afterProcessAbort(WorkflowEvent event) {
}
/**
* 流程节点动作
*/
default void onBeforeNodeLeft(WorkflowNodeEvent event) {
}
/**
* 流程结束(通过)
*/
default void onApproved(WorkflowEvent event, Bill bill) {
}
/**
* 流程结束(驳回)
*/
default void onRejected(WorkflowEvent event, Bill bill) {
}
/**
* 当前节点触发,还没有开始做业务处理之前
*/
default void onBeforeNodeTriggered(WorkflowNodeEvent event) {
}
/**
* 当前节点触发,生成UserTask之后触发
*/
default void onAfterNodeTriggered(WorkflowNodeEvent event){
}
default Bill getBill(WorkflowEvent event) {
BillDefine define = SpringBeanUtils.getBean(BillDefineService.class).getBillDefine(event.getBizName());
return SpringBeanUtils.getBean(BillService.class).restoreBill(define, getBillDataObj(event));
}
default KObject getBillDataObj(WorkflowEvent event) {
if (event.getBizObj() != null) {
return event.getBizObj();
}
BillDefine define = SpringBeanUtils.getBean(BillDefineService.class).getBillDefine(event.getBizName());
KClass clz = define.getDataType();
return SpringBeanUtils.getBean(BillDataDao.class).get(clz, event.getBizObjId()).createCopy();
}
}
CustomBillWorkflowListener接口和BillWorkflowListener类结合使用了观察者模式。观察者模式是一种行为设计模式,其中一个对象(称为主题)维护一系列依赖于它的对象(称为观察者),当主题发生变化时,它会通知所有的观察者进行相应的处理。
具体来说:
- CustomBillWorkflowListener接口定义了一系列的观察者方法,用于处理不同的工作流事件。
- BillWorkflowListener类作为主题,实现了这些观察者方法,并在各个事件点调用CustomBillWorkflowListener接口中对应的方法。
- BillWorkflowListener类内部维护了一个customWorkflowListeners,用于存储所有的CustomBillWorkflowListener实例。
- 在BillWorkflowListener类中,通过performCustomListener方法遍历customWorkflowListeners,找到支持当前事件的CustomBillWorkflowListener实例,并调用其方法来处理相应的事件。
通过观察者模式,BillWorkflowListener类和CustomBillWorkflowListener接口之间实现了解耦,BillWorkflowListener作为主题可以根据需要通知不同的观察者来处理工作流事件,同时也允许新增或移除观察者而不需要修改主题代码。
代码补充
在上一标题代码实现中BillWorkflowListener使用到了Consumer类来简化代码的编写,还可以使用反射的形式来实现,代码如下:
public class BillWorkflowListenerInvoker extends CommonBillWorkflowListener {
// 反射调用CustomBillWorkflowListener方法
private void invokeCustomListeners(String methodName, WorkflowEvent event) {
List<CustomBillWorkflowListener> listeners = getCustomListeners();
// 遍历并调用监听器方法
for (CustomBillWorkflowListener listener : listeners) {
if (listener.supportByEvent(event)) {
invokeMethod(listener, methodName, event);
}
}
}
// 获取所有CustomBillWorkflowListener的实例
private List<CustomBillWorkflowListener> getCustomListeners() {
List<CustomBillWorkflowListener> listeners = new ArrayList<>();
return listeners;
}
// 反射调用方法
private void invokeMethod(CustomBillWorkflowListener listener, String methodName, WorkflowEvent event) {
try {
Method method = listener.getClass().getMethod(methodName, WorkflowEvent.class);
method.invoke(listener, event);
} catch (Exception e) {
// 处理异常
e.printStackTrace();
}
}
/**
* 提交前
*/
@Override
public void beforeProcessStart(WorkflowEvent event) {
super.beforeProcessStart(event);
invokeCustomListeners("beforeProcessStart", event);
}
/**
* 提交后
*/
@Override
public void afterProcessStart(WorkflowEvent event) {
super.afterProcessStart(event);
invokeCustomListeners("afterProcessStart", event);
}
}