【Java设计模式】数据总线模式:高效统一组件通信
文章目录
- 【Java设计模式】数据总线模式:高效统一组件通信
- 一、概述
- 二、详细解释及实际示例
- 三、Java中数据总线模式的编程示例
- 四、何时在Java中使用数据总线模式
- 五、数据总线模式在Java中的实际应用
- 六、数据总线模式的优点和权衡
- 七、源码下载
【Java设计模式】数据总线模式:高效统一组件通信
一、概述
数据总线设计模式旨在提供一个集中式的通信通道,通过该通道,系统的各个组件可以交换数据而无需直接连接,从而促进松散耦合,并增强可扩展性和可维护性。
二、详细解释及实际示例
- 实际示例:
- 考虑一个大型机场作为数据总线模式的类似现实世界示例。在机场中,各种航空公司、乘客、行李搬运工和安全人员都需要进行通信和共享信息。与其让每个实体直接与其他每个实体进行通信,机场使用了一个集中式的公告系统(数据总线)。航班信息、安全警报和其他关键更新通过这个系统进行广播,每个实体都监听与它们相关的消息。这种设置允许机场解耦通信过程,确保每个实体仅接收它们所需的信息,同时允许系统进行扩展并集成新的实体,而不会干扰现有的实体。这类似于Java中的数据总线模式促进集中式通信和事件处理,增强系统的可扩展性和可维护性。
- 通俗解释:
- 数据总线是一种设计模式,它根据传输的消息或事件的类型连接应用程序的组件进行通信。这种模式促进了解耦,通过允许组件在没有直接依赖关系的情况下进行通信,使系统更容易扩展和维护。
三、Java中数据总线模式的编程示例
假设您有一个应用程序,支持在线预订和参与活动。您希望该应用程序向社区或组织的所有普通成员发送通知,例如活动广告,但不想向活动管理员或组织者发送此类广告。相反,您希望向他们发送有关向所有成员发送新广告的时间的通知。数据总线使您能够通过使它们的类或组件仅接受特定类型的消息,按类型(普通成员或活动管理员)有选择地通知社区成员。因此,普通成员和管理员不需要相互了解,也不需要了解用于通知整个社区的具体类或组件,除了知道发送的消息类型。
在上面的在线活动应用程序示例中,我们首先定义我们的Member
接口及其实现:MessageCollectorMember
(普通社区成员)和StatusMember
(活动管理员或组织者)。
public interface Member extends Consumer<DataType> {
void accept(DataType event);
}
接下来,我们实现一个数据总线来订阅或取消订阅成员,并发布事件以通知所有社区成员。
public class DataBus {
private static final DataBus INSTANCE = new DataBus();
private final Set<Member> listeners = new HashSet<>();
public static DataBus getInstance() {
return INSTANCE;
}
public void subscribe(final Member member) {
this.listeners.add(member);
}
public void unsubscribe(final Member member) {
this.listeners.remove(member);
}
public void publish(final DataType event) {
event.setDataBus(this);
listeners.forEach(
listener -> listener.accept(event));
}
}
在publish
方法中,对每个成员应用accept
方法。
对于普通社区成员(MessageCollectorMember
),accept
方法只能处理MessageData
类型的消息。
public class MessageCollectorMember implements Member {
private final String name;
private final List<String> messages = new ArrayList<>();
public MessageCollectorMember(String name) {
this.name = name;
}
@Override
public void accept(final DataType data) {
if (data instanceof MessageData) {
handleEvent((MessageData) data);
}
}
}
对于活动管理员或组织者(StatusMember
),accept
方法可以处理StartingData
和StoppingData
类型的消息。
public class StatusMember implements Member {
private final int id;
private LocalDateTime started;
private LocalDateTime stopped;
public StatusMember(int id) {
this.id = id;
}
@Override
public void accept(final DataType data) {
if (data instanceof StartingData) {
handleEvent((StartingData) data);
} else if (data instanceof StoppingData) {
handleEvent((StoppingData) data);
}
}
}
以下是App
类,用于演示数据总线模式的实际应用:
class App {
public static void main(String[] args) {
final var bus = DataBus.getInstance();
bus.subscribe(new StatusMember(1));
bus.subscribe(new StatusMember(2));
final var foo = new MessageCollectorMember("Foo");
final var bar = new MessageCollectorMember("Bar");
bus.subscribe(foo);
bus.publish(StartingData.of(LocalDateTime.now()));
}
}
当数据总线发布消息时,输出如下:
02:33:57.627 [main] INFO com.iluwatar.databus.members.StatusMember - Receiver 2 sees application started at 2022 - 10 - 26T02:33:57.613529100
02:33:57.633 [main] INFO com.iluwatar.databus.members.StatusMember - Receiver 1 sees application started at 2022 - 10 - 26T02:33:57.613529100
如所示,MessageCollectorMembers
仅接受MessageData
类型的消息,因此它们不会看到StartingData
或StoppingData
消息,这些消息仅对StatusMember
(活动管理员或组织者)可见。这种选择性的消息处理可防止普通社区成员接收管理通知。
四、何时在Java中使用数据总线模式
- 当多个组件需要共享数据或事件,但不希望直接耦合时。
- 在复杂的、事件驱动的系统中,信息的流动动态变化。
- 在分布式系统中,组件可能部署在不同的环境中。
- 在微服务架构中用于服务间通信。
五、数据总线模式在Java中的实际应用
- 大规模应用程序中的事件处理系统。
- 微服务架构中用于服务间通信。
- 实时数据处理系统,如股票交易平台。
- 在Spring等框架中,特别是其应用程序事件机制。
六、数据总线模式的优点和权衡
优点:
- 松散耦合:组件可以相互交互,而无需相互直接依赖。
- 灵活性:可以添加新的订阅者或发布者,而不会影响现有组件。
- 可扩展性:该模式支持独立扩展组件。
- 可重用性:总线和组件可以在不同的系统中重用。
权衡:
- 复杂性:引入数据总线可能会增加系统架构的复杂性。
- 性能开销:额外的通信层可能会引入延迟。
- 调试难度:跟踪通过总线的数据流可能具有挑战性,特别是在具有许多事件的系统中。
七、源码下载
数据总线模式示例代码下载