Bootstrap

中介者模式 (Mediator Pattern)

好的,我们来深入探讨 中介者模式 (Mediator Pattern),并结合 多个事件通道(Event Channels)多个事件处理器(Event Processors) 的场景进行详细的讲解。

中介者模式的详细讲解

在更复杂的事件驱动架构中,系统中的各个组件可能涉及不同的事件流。每个事件通道 (Event Channel) 和事件处理器 (Event Processor) 可能负责处理不同种类的事件或不同的业务逻辑。通过引入中介者模式,可以有效地协调和解耦这些组件,确保它们之间的独立性和灵活性。

核心角色及其功能:
  1. 事件 (Event):表示系统中的某种行为或状态变化(例如:订单创建、用户登录)。
  2. 事件队列 (Event Queue):存储所有的事件,按序列管理,确保事件的顺序性。
  3. 事件通道 (Event Channel):负责将事件分发到相关的事件处理器。
  4. 事件中介者 (Event Mediator):负责接收事件,并决定将事件传递给哪些事件通道,最终由事件通道把事件传递给具体的事件处理器。
  5. 事件处理器 (Event Processor):负责具体处理事件的逻辑,如更新数据库、发送通知等。

架构流程

事件流的高级流程:
  1. 事件的产生:当用户提交订单时,产生了一个“订单创建事件”。
  2. 事件加入队列:事件被加入到 事件队列 中,等待被处理。
  3. 事件的路由:事件通过 事件中介者,它负责判断事件的类型,并将事件分发到合适的 事件通道
  4. 事件的处理:每个事件通道将事件分发到不同的 事件处理器,每个事件处理器根据事件的内容处理业务逻辑。
  5. 事件处理完毕:事件处理完毕后,相关的状态更新或其他后续操作会被执行。

复杂的多通道与多处理器模式

在复杂系统中,可能有多个事件通道,每个事件通道会根据事件类型将事件分发给不同的处理器。每个处理器负责处理特定类型的事件。

例如:

  • 订单相关事件通道:负责处理所有与订单相关的事件(订单创建、支付、发货等)。
  • 库存相关事件通道:处理库存变动、库存调整等事件。
  • 通知事件通道:处理发送通知、消息等任务。

这种设计使得每个事件处理器只专注于处理特定类型的事件,降低了各个组件之间的耦合度,同时提高了灵活性和可扩展性。


UML 事件处理流程图

为了清晰表达这一架构,我们将使用 UML 序列图 来展示一个复杂的事件驱动架构,涉及多个事件通道与事件处理器的情况。

User "Event Queue" "Event Mediator" "Event Channel (Order)" "Event Channel (Stock)" "Event Channel (Notify)" "Order Processor" "Stock Processor" "Notify Processor" Create Order Event Enqueue Event Route Order Event Route Stock Event Route Notify Event Process Order Event Process Stock Event Process Notify Event User "Event Queue" "Event Mediator" "Event Channel (Order)" "Event Channel (Stock)" "Event Channel (Notify)" "Order Processor" "Stock Processor" "Notify Processor"
图中的角色解释
  1. Event Source(事件源): 触发事件的源,如用户点击按钮、订单创建等。
  2. Event Queue(事件队列): 存储待处理的事件,确保事件有序、及时地被处理。
  3. Event Mediator(事件中介者): 作为中心化的控制器,决定事件需要被哪个通道处理。
  4. Event Channel(事件通道): 根据事件的类型,将事件分发给不同的事件处理器。可以有多个通道(如订单通道、库存通道、通知通道)。
  5. Event Processor(事件处理器): 具体负责处理事件的业务逻辑。

Java 代码实现

假设我们有一个电商系统,在系统中,当订单创建时,事件会通过不同的事件通道进行分发和处理。每个事件通道都会分发事件到特定的处理器。

代码示例
// 事件类
public class OrderEvent {
    private String orderId;
    private String eventType;

    public OrderEvent(String orderId, String eventType) {
        this.orderId = orderId;
        this.eventType = eventType;
    }

    public String getOrderId() {
        return orderId;
    }

    public String getEventType() {
        return eventType;
    }
}

// 事件队列
import java.util.LinkedList;
import java.util.Queue;

public class EventQueue {
    private Queue<OrderEvent> eventQueue = new LinkedList<>();

    public void enqueue(OrderEvent event) {
        eventQueue.add(event);
    }

    public OrderEvent dequeue() {
        return eventQueue.poll();
    }
}

// 事件中介者
public class EventMediator {
    private EventQueue eventQueue;
    private EventChannel orderChannel;
    private EventChannel stockChannel;
    private EventChannel notifyChannel;

    public EventMediator(EventQueue eventQueue, EventChannel orderChannel, EventChannel stockChannel, EventChannel notifyChannel) {
        this.eventQueue = eventQueue;
        this.orderChannel = orderChannel;
        this.stockChannel = stockChannel;
        this.notifyChannel = notifyChannel;
    }

    public void processEvents() {
        OrderEvent event = eventQueue.dequeue();
        if (event != null) {
            // 根据事件类型,路由到不同的事件通道
            if ("OrderCreated".equals(event.getEventType())) {
                orderChannel.routeEvent(event);
            } else if ("StockUpdate".equals(event.getEventType())) {
                stockChannel.routeEvent(event);
            } else if ("Notification".equals(event.getEventType())) {
                notifyChannel.routeEvent(event);
            }
        }
    }
}

// 事件通道
public class EventChannel {
    private EventProcessor processor;

    public EventChannel(EventProcessor processor) {
        this.processor = processor;
    }

    public void routeEvent(OrderEvent event) {
        processor.processEvent(event);
    }
}

// 事件处理器
public class EventProcessor {
    private String processorName;

    public EventProcessor(String processorName) {
        this.processorName = processorName;
    }

    public void processEvent(OrderEvent event) {
        System.out.println("Processor " + processorName + " is handling event for Order ID: " + event.getOrderId());
        // 具体的事件处理逻辑,如更新数据库、发送通知等
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        // 创建事件队列
        EventQueue eventQueue = new EventQueue();

        // 创建事件通道和事件处理器
        EventProcessor orderProcessor = new EventProcessor("Order Processor");
        EventProcessor stockProcessor = new EventProcessor("Stock Processor");
        EventProcessor notifyProcessor = new EventProcessor("Notify Processor");

        EventChannel orderChannel = new EventChannel(orderProcessor);
        EventChannel stockChannel = new EventChannel(stockProcessor);
        EventChannel notifyChannel = new EventChannel(notifyProcessor);

        // 创建事件中介者
        EventMediator mediator = new EventMediator(eventQueue, orderChannel, stockChannel, notifyChannel);

        // 事件发生,订单创建
        OrderEvent orderCreatedEvent = new OrderEvent("12345", "OrderCreated");
        eventQueue.enqueue(orderCreatedEvent);

        // 事件中介者处理事件
        mediator.processEvents();
    }
}
代码解释
  1. OrderEvent:表示事件类,包含事件类型和订单ID。
  2. EventQueue:事件队列,用来缓存所有的事件。
  3. EventMediator:事件中

介者,负责从队列中取出事件并将其分发到对应的事件通道。
4. EventChannel:事件通道,负责将事件传递给具体的事件处理器。
5. EventProcessor:事件处理器,具体负责处理事件。

通过引入中介者模式,事件处理流程变得更加清晰,系统的解耦性也得到了提升。

结合DDD改造

项目结构与文件作用说明

以下是文件结构及每个文件的作用和使用场景,结合 领域驱动设计(DDD)事件驱动架构

src
├── com
│   └── example
│       ├── domain
│       │   ├── order
│       │   │   ├── OrderAggregate.java  <-- 处理与订单相关的业务逻辑
│       │   │   ├── OrderCreatedEvent.java  <-- 领域事件,表示订单创建的事件
│       │   ├── inventory
│       │   │   ├── InventoryAggregate.java  <-- 处理与库存相关的业务逻辑
│       ├── service
│       │   ├── OrderService.java  <-- 订单服务,调用 `OrderAggregate` 进行订单创建等业务逻辑
│       │   ├── InventoryService.java  <-- 库存服务,处理库存检查和库存更新
│       │   ├── NotificationService.java  <-- 发送通知的服务
│       ├── mediator
│       │   ├── EventMediator.java  <-- 事件中介者,负责监听和处理事件
│       ├── event
│       │   ├── Event.java  <-- 事件接口,定义事件的通用行为
│       │   ├── EventChannel.java  <-- 事件通道,用于发布和订阅事件
│       │   ├── EventProcessor.java  <-- 事件处理器接口,定义事件处理的规则
│       │   ├── EventQueue.java  <-- 事件队列,用于存储待处理的事件
│       └── notification
│           ├── NotificationService.java  <-- 发送通知的服务,实际发送业务相关的通知

文件说明与使用场景
1. OrderCreatedEvent.java:领域事件(Domain Event)
  • 作用:表示当订单创建时,系统需要发出的事件。领域事件是业务流程中的关键动作,用来触发其他的业务流程。
  • 场景:订单一旦创建,就需要通过事件来通知其他系统模块(如库存、通知服务等),以进行相应的业务操作。
public class OrderCreatedEvent {
    private String orderId;
    private LocalDateTime createdAt;
    
    public OrderCreatedEvent(String orderId) {
        this.orderId = orderId;
        this.createdAt = LocalDateTime.now();
    }

    public String getOrderId() {
        return orderId;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
}
2. OrderAggregate.java:聚合根(Aggregate Root)
  • 作用:处理与订单相关的核心业务逻辑。聚合根是一个业务模型,处理业务规则,确保状态的一致性。聚合根在 DDD 中的作用是统一管理领域对象,保证业务逻辑的完整性。
  • 场景:聚合根作为业务实体,处理订单的创建、状态更改等业务。
public class OrderAggregate {
    private String orderId;
    private String status;

    public OrderAggregate(String orderId) {
        this.orderId = orderId;
        this.status = "Created"; // 初始化订单状态
    }

    public void createOrder() {
        System.out.println("Order " + orderId + " has been created.");
        EventChannel.publish(new OrderCreatedEvent(orderId));  // 订单创建时发布事件
    }

    public String getStatus() {
        return status;
    }

    public String getOrderId() {
        return orderId;
    }
}
3. InventoryAggregate.java:库存聚合根(Inventory Aggregate)
  • 作用:处理与库存相关的业务逻辑。类似于 OrderAggregate,它是一个聚合根,负责管理库存的状态及库存操作。
  • 场景:当创建订单时,系统需要检查库存是否充足。如果库存充足,则减少库存量;否则提示缺货。
public class InventoryAggregate {
    private String productId;
    private int stockLevel;

    public InventoryAggregate(String productId) {
        this.productId = productId;
        this.stockLevel = 100; // 初始库存为100
    }

    public boolean checkStock() {
        return stockLevel > 0;
    }

    public void decreaseStock() {
        stockLevel--;
    }
}
4. OrderService.java:订单服务(Order Service)
  • 作用:订单服务协调 OrderAggregate 的操作,负责调用订单的创建方法。
  • 场景:用户提交订单时,服务会调用 OrderAggregate 创建订单,并触发相关的领域事件。
public class OrderService {
    public void createOrder(String orderId) {
        OrderAggregate orderAggregate = new OrderAggregate(orderId);
        orderAggregate.createOrder();  // 调用聚合根的方法,创建订单并发布事件
    }
}
5. InventoryService.java:库存服务(Inventory Service)
  • 作用:库存服务检查库存,若库存足够,则减少库存。
  • 场景:当订单创建后,库存服务需要检查相关商品的库存,并对库存进行减少操作。
public class InventoryService {
    public void checkInventory(String productId) {
        InventoryAggregate inventoryAggregate = new InventoryAggregate(productId);
        if (inventoryAggregate.checkStock()) {
            inventoryAggregate.decreaseStock();  // 库存充足,减少库存
            System.out.println("Inventory updated, stock level decreased.");
        } else {
            System.out.println("Out of stock.");
        }
    }
}
6. NotificationService.java:通知服务(Notification Service)
  • 作用:处理发送通知的业务逻辑,如通知用户订单创建成功。
  • 场景:订单创建后,通知服务会发送订单创建的通知给用户或相关系统。
public class NotificationService {
    public void sendNotification(String message) {
        System.out.println("Sending notification: " + message);  // 发送通知
    }
}
7. EventChannel.java:事件通道(Event Channel)
  • 作用:负责发布和订阅事件。它是一个简单的事件总线,用于解耦事件发布者和事件消费者。
  • 场景:当领域事件如 OrderCreatedEvent 被发布时,EventChannel 会负责将事件分发给适当的处理者(例如,库存服务、通知服务)。
public class EventChannel {
    private static final Map<String, EventProcessor> subscribers = new HashMap<>();

    public static void subscribe(String eventType, EventProcessor processor) {
        subscribers.put(eventType, processor);
    }

    public static void publish(Object event) {
        String eventType = event.getClass().getSimpleName();
        EventProcessor processor = subscribers.get(eventType);
        if (processor != null) {
            processor.process(event);  // 执行事件处理
        }
    }
}
8. EventProcessor.java:事件处理器接口(Event Processor)
  • 作用:定义了事件处理的接口,所有事件处理器都需要实现 process 方法。
  • 场景:每个事件处理器根据事件类型来处理业务逻辑。
public interface EventProcessor {
    void process(Object event);
}
9. EventMediator.java:事件中介者(Mediator)
  • 作用:监听和路由事件,协调不同模块间的通信,避免直接的依赖关系。
  • 场景EventMediator 监听事件(如 OrderCreatedEvent),当事件触发时,它协调其他服务(如库存服务和通知服务)进行相应处理。
public class EventMediator {
    private OrderService orderService = new OrderService();
    private InventoryService inventoryService = new InventoryService();
    private NotificationService notificationService = new NotificationService();

    public EventMediator() {
        EventChannel.subscribe("OrderCreatedEvent", this::onOrderCreated);
    }

    public void onOrderCreated(Object event) {
        if (event instanceof com.example.domain.order.OrderCreatedEvent) {
            com.example.domain.order.OrderCreatedEvent orderCreatedEvent = (com.example.domain.order.OrderCreatedEvent) event;
            inventoryService.checkInventory("product-id");  // 调用库存服务
            notificationService.sendNotification("Order " + orderCreatedEvent.getOrderId() + " created successfully.");
        }
    }
}
10. MainApp.java:主应用程序(Main Application)
  • 作用:模拟整个应用的启动,创建订单并触发事件。
  • 场景:用户提交订单后,MainApp 会通过 OrderService 创建订单,并触发事件到 EventMediator,完成业务流程。
public class MainApp {
    public static void main(String[] args) {
        EventMediator mediator = new EventMediator();

        // 模拟用户创建订单
        OrderService orderService = new OrderService();
        orderService.createOrder("order-123");
    }
}

总结

  • 每个文件的作用和场景都符合 领域驱动设计(DDD) 的原则,聚焦于业务

领域的实现与解耦。

  • 领域事件通过 EventChannel 发布,系统模块(如库存、通知)通过事件中介者 EventMediator 处理事件,实现业务逻辑的流转。
  • 该架构有效地将领域逻辑与基础设施(如事件发布与处理)解耦,便于系统扩展和维护。
;