
本文介绍如何使用命令模式统一事件处理流程,并结合访问者模式或策略式错误处理器,彻底消除 instanceof 类型判断的 if-else 耦合,提升面向对象设计的可扩展性与可维护性。
本文介绍如何使用命令模式统一事件处理流程,并结合访问者模式或策略式错误处理器,彻底消除 `instanceof` 类型判断的 if-else 耦合,提升面向对象设计的可扩展性与可维护性。
在原始代码中,EventProcessor 类通过硬编码的 if (result instanceof XxxError) 分支分别处理不同错误类型,导致逻辑分散、重复且难以扩展——每当新增错误子类或事件类型,就必须修改多处 onEventX() 方法。这种设计违反了开闭原则(OCP)和单一职责原则(SRP)。根本解法在于将“行为”与“决策”解耦:用命令模式封装执行逻辑,用错误处理器(基于访问者或策略模式)统一响应错误。
✅ 推荐重构方案:命令 + 错误策略处理器
我们不采用原文中 Command#getError() 硬编码错误生成的方式(这违背了命令职责),而是聚焦核心目标:消除 instanceof 分支。以下是生产就绪的重构步骤:
1. 定义统一事件接口与错误处理器
// 统一事件契约(Event1/Event2 实现此接口)
public interface Event {
void setStatus(EventStatus status);
}
// 错误处理器:为每种错误定义专属处理逻辑
public interface ErrorHandler {
void handle(NoProcessorFoundError error, Event event);
void handle(UnknownError error, Event event);
// 新增错误类型时,仅需在此接口添加新方法(符合OCP)
}
2. 使用访问者模式消除 instanceof(推荐)
// 错误基类支持访问者
public abstract class Error {
public abstract <t> T accept(ErrorVisitor<t> visitor);
}
public interface ErrorVisitor<t> {
T visit(NoProcessorFoundError error);
T visit(UnknownError error);
}
// 具体错误实现
public class NoProcessorFoundError extends Error {
@Override
public <t> T accept(ErrorVisitor<t> visitor) {
return visitor.visit(this);
}
}
public class UnknownError extends Error {
@Override
public <t> T accept(ErrorVisitor<t> visitor) {
return visitor.visit(this);
}
}</t></t></t></t></t></t></t>
3. 命令类封装事件处理与状态更新
public abstract class EventCommand<t extends event> {
protected final T event;
public EventCommand(T event) {
this.event = event;
}
// 模板方法:执行处理 → 解析结果 → 委托给错误处理器
public final void execute() {
Error result = doProcess();
if (result != null) {
new ErrorStatusHandler().handle(result, event);
}
}
protected abstract Error doProcess();
// 内部错误处理器:集中定义状态映射规则
private static class ErrorStatusHandler implements ErrorHandler {
@Override
public void handle(NoProcessorFoundError error, Event event) {
event.setStatus(EventStatus.RETRYABLE); // 或 REJECTED,按事件类型动态决定
}
@Override
public void handle(UnknownError error, Event event) {
event.setStatus(EventStatus.FAILED);
}
}
}
// 具体命令实现(无重复 if-else)
public class ProcessEvent1Command extends EventCommand<event1> {
public ProcessEvent1Command(Event1 event) {
super(event);
}
@Override
protected Error doProcess() {
return Event1Processors.process(event); // 返回具体错误实例
}
}
public class ProcessEvent2Command extends EventCommand<event2> {
public ProcessEvent2Command(Event2 event) {
super(event);
}
@Override
protected Error doProcess() {
return Event2Processors.process(event);
}
}</event2></event1></t>
4. 使用示例(简洁、可测试、易扩展)
// 事件处理入口
public class EventProcessor {
public void onEvent1(Event1 event) {
new ProcessEvent1Command(event).execute();
}
public void onEvent2(Event2 event) {
new ProcessEvent2Command(event).execute();
}
}
// 单元测试友好:可直接 new Command(...).execute()
@Test
void testNoProcessorFoundError_setsRetryable() {
Event1 event = new Event1();
new ProcessEvent1Command(event) {
@Override
protected Error doProcess() {
return new NoProcessorFoundError(); // 模拟返回
}
}.execute();
assertEquals(EventStatus.RETRYABLE, event.getStatus());
}
⚠️ 注意事项与最佳实践
-
避免过度设计:若错误类型极少且稳定,可直接用 Map
, BiConsumer> 策略注册表替代访问者,更轻量; - 状态映射应解耦:RETRYABLE/REJECTED 等状态不应硬编码在处理器中,建议通过 EventContext 或配置中心注入;
-
异常 vs 错误对象:考虑将 Error 改为 Result
(如 Result.success(data) / Result.failure(error)),更符合函数式风格; - 命令组合:后续可扩展 CompositeCommand 支持事务性多事件处理。
通过该重构,instanceof 分支彻底消失,新增错误类型只需:
- 继承 Error 并实现 accept();
- 在 ErrorHandler 中添加对应 handle() 方法;
- 在 ErrorStatusHandler 中补充处理逻辑。
零侵入现有命令类,真正实现高内聚、低耦合的 OO 设计。










