当前位置: 首页 > news >正文

设计模式(C++)详解——中介者模式(3)

<摘要>
中介者模式是一种行为设计模式,通过引入中介者对象来封装一组对象之间的交互,从而降低对象间的耦合度。本文将详细解析中介者模式的背景概念、设计意图、实现方式及应用场景,通过聊天室系统、飞机调度系统和UI组件交互三个完整案例,结合C++代码实现和Mermaid图表,全面展示该模式的实际应用价值。


<解析>

中介者模式深度解析

1. 背景与核心概念

1.1 起源与发展历程

中介者模式的诞生可以追溯到软件工程中"高内聚、低耦合"的设计原则。在早期的面向对象设计中,开发人员经常遇到这样的困境:当多个对象需要相互通信时,直接的对象引用会导致复杂的网状依赖关系。

发展脉络

  • 1987年:在Smalltalk语言的MVC框架中首次出现了类似中介者的概念
  • 1994年:Gamma等人在《设计模式》一书中正式提出并定义了中介者模式
  • 2000年代:随着GUI框架和企业级应用的发展,中介者模式得到广泛应用
  • 现今:在微服务架构、事件驱动系统中,中介者模式的思想被重新诠释和应用

1.2 核心概念解析

中介者模式的核心思想是:用一个中介对象来封装一系列的对象交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互

关键术语

术语英文说明
中介者Mediator定义对象间交互的接口
具体中介者ConcreteMediator实现中介者接口,协调各同事对象
同事类Colleague定义同事类的接口,持有中介者引用
具体同事类ConcreteColleague实现同事类接口,只与中介者通信

1.3 UML类图解析

knows
mediator
«abstract»
Mediator
+notify(sender Colleague, event string) : void
ConcreteMediator
-colleague1 ConcreteColleague1
-colleague2 ConcreteColleague2
-colleague3 ConcreteColleague3
+notify(sender Colleague, event string) : void
+registerColleague1(colleague ConcreteColleague1) : void
+registerColleague2(colleague ConcreteColleague2) : void
+registerColleague3(colleague ConcreteColleague3) : void
«abstract»
Colleague
#mediator Mediator
+setMediator(mediator Mediator) : void
+send(message string) : void
+receive(message string) : void
ConcreteColleague1
-name string
+ConcreteColleague1(name string)
+send(message string) : void
+receive(message string) : void
ConcreteColleague2
-name string
+ConcreteColleague2(name string)
+send(message string) : void
+receive(message string) : void
ConcreteColleague3
-name string
+ConcreteColleague3(name string)
+send(message string) : void
+receive(message string) : void

图表解读

  • Mediator:抽象中介者,定义通信接口
  • ConcreteMediator:具体中介者,维护同事对象引用,实现复杂的协调逻辑
  • Colleague:同事抽象类,包含中介者引用
  • ConcreteColleague:具体同事类,通过中介者与其他对象通信

2. 设计意图与考量

2.1 核心设计目标

中介者模式的核心设计目标可以用"解耦"二字概括,具体体现在:

  1. 降低耦合度:将网状依赖变为星状依赖
  2. 集中控制:将交互逻辑集中到中介者中
  3. 简化对象职责:每个对象只需关注自身业务逻辑
  4. 提高复用性:同事类可以独立复用

2.2 设计权衡因素

优势

  • ✅ 减少类间依赖,降低耦合
  • ✅ 简化对象协议,一对多交互变为一对一
  • ✅ 抽象对象交互,便于理解和维护
  • ✅ 符合迪米特法则(最少知识原则)

劣势

  • ❌ 中介者可能变得过于复杂,成为"上帝对象"
  • ❌ 增加了系统的中间层,可能影响性能
  • ❌ 中介者本身的修改可能影响整个系统

2.3 适用场景分析

适合使用中介者模式的场景

  • 对象间存在复杂的网状引用关系
  • 一个对象引用很多其他对象,直接通信导致难以复用
  • 想在多个对象间定制交互行为,又不想生成太多子类
  • 交互行为需要定义在不同对象间,但又不想分散在各个类中

3. 实例与应用场景

3.1 案例一:智能聊天室系统

场景描述
设计一个多人聊天室系统,用户可以向所有人广播消息,也可以私聊特定用户,同时需要支持用户加入、离开的通知。

实现方案

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <memory>// 前向声明
class User;/*** @brief 聊天室中介者接口* * 定义用户间通信的标准接口,负责协调所有用户对象之间的交互*/
class ChatMediator {
public:virtual ~ChatMediator() = default;/*** @brief 发送消息到所有用户* * @param message 消息内容* @param sender 发送者*/virtual void broadcastMessage(const std::string& message, const std::string& sender) = 0;/*** @brief 发送私聊消息* * @param message 消息内容* @param sender 发送者* @param receiver 接收者*/virtual void privateMessage(const std::string& message,const std::string& sender,const std::string& receiver) = 0;/*** @brief 用户加入聊天室* * @param user 用户对象*/virtual void addUser(std::shared_ptr<User> user) = 0;/*** @brief 用户离开聊天室* * @param username 用户名*/virtual void removeUser(const std::string& username) = 0;
};/*** @brief 用户抽象类(同事类)* * 定义用户的基本行为和属性,持有中介者引用*/
class User {
protected:std::string username_;std::shared_ptr<ChatMediator> mediator_;public:User(const std::string& username, std::shared_ptr<ChatMediator> mediator): username_(username), mediator_(mediator) {}virtual ~User() = default;/*** @brief 获取用户名* * @return std::string 用户名*/std::string getUsername() const { return username_; }/*** @brief 发送广播消息* * @param message 消息内容*/virtual void sendMessage(const std::string& message) {std::cout << username_ << " 发送广播: " << message << std::endl;mediator_->broadcastMessage(message, username_);}/*** @brief 发送私聊消息* * @param message 消息内容* @param receiver 接收者用户名*/virtual void sendPrivateMessage(const std::string& message, const std::string& receiver) {std::cout << username_ << " 私聊 " << receiver << ": " << message << std::endl;mediator_->privateMessage(message, username_, receiver);}/*** @brief 接收消息* * @param message 消息内容* @param sender 发送者*/virtual void receiveMessage(const std::string& message, const std::string& sender) = 0;
};/*** @brief 具体用户类* * 实现具体的用户行为,可以扩展不同的用户类型*/
class ChatUser : public User {
public:ChatUser(const std::string& username, std::shared_ptr<ChatMediator> mediator): User(username, mediator) {}void receiveMessage(const std::string& message, const std::string& sender) override {std::cout << username_ << " 收到来自 " << sender << " 的消息: " << message << std::endl;}
};/*** @brief 具体聊天室中介者* * 实现聊天室的具体逻辑,管理所有用户和消息路由*/
class ConcreteChatMediator : public ChatMediator {
private:std::unordered_map<std::string, std::shared_ptr<User>> users_;public:void broadcastMessage(const std::string& message, const std::string& sender) override {std::cout << "=== 聊天室广播 === (" << sender << "): " << message << std::endl;for (const auto& pair : users_) {if (pair.first != sender) {  // 不发送给自己pair.second->receiveMessage(message, sender);}}}void privateMessage(const std::string& message,const std::string& sender,const std::string& receiver) override {std::cout << "=== 私聊消息 === [" << sender << " -> " << receiver << "]: " << message << std::endl;auto it = users_.find(receiver);if (it != users_.end()) {it->second->receiveMessage("[私聊] " + message, sender);} else {// 通知发送者接收者不存在auto senderIt = users_.find(sender);if (senderIt != users_.end()) {senderIt->second->receiveMessage("错误: 用户 " + receiver + " 不存在", "系统");}}}void addUser(std::shared_ptr<User> user) override {std::string username = user->getUsername();users_[username] = user;// 通知所有用户有新用户加入broadcastMessage("用户 " + username + " 加入了聊天室", "系统");}void removeUser(const std::string& username) override {auto it = users_.find(username);if (it != users_.end()) {users_.erase(it);broadcastMessage("用户 " + username + " 离开了聊天室", "系统");}}
};// 演示代码
int main() {// 创建聊天室中介者auto chatMediator = std::make_shared<ConcreteChatMediator>();// 创建用户auto user1 = std::make_shared<ChatUser>("Alice", chatMediator);auto user2 = std::make_shared<ChatUser>("Bob", chatMediator);auto user3 = std::make_shared<ChatUser>("Charlie", chatMediator);// 用户加入聊天室chatMediator->addUser(user1);chatMediator->addUser(user2);chatMediator->addUser(user3);std::cout << "\n=== 聊天开始 ===\n" << std::endl;// 用户间通信user1->sendMessage("大家好!");user2->sendMessage("你好,Alice!");user1->sendPrivateMessage("嘿,Bob,有个秘密要告诉你", "Bob");user3->sendMessage("我也可以看到广播消息");// Bob离开聊天室chatMediator->removeUser("Bob");// 再次尝试给Bob发消息user1->sendPrivateMessage("Bob,你还在吗?", "Bob");return 0;
}

时序图分析

AliceChatMediatorBobCharlie用户加入聊天室addUser(Alice)receiveMessage("Alice加入", "系统")receiveMessage("Alice加入", "系统")广播消息流程sendMessage("大家好!")receiveMessage("大家好!", "Alice")receiveMessage("大家好!", "Alice")私聊消息流程sendPrivateMessage("秘密", "Bob")receiveMessage("[私聊] 秘密", "Alice")用户离开removeUser("Bob")receiveMessage("Bob离开", "系统")receiveMessage("Bob离开", "系统")AliceChatMediatorBobCharlie

3.2 案例二:飞机调度系统

场景描述
设计一个航空管制系统,多架飞机需要与塔台通信,飞机之间不能直接通信,必须通过塔台中介者来协调起飞、降落和航线冲突。

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>// 飞机状态枚举
enum class FlightStatus {ON_GROUND,TAKING_OFF,IN_AIR,LANDING
};/*** @brief 航空管制中介者接口* * 协调所有飞机的起降和飞行状态,避免冲突*/
class AirTrafficControl {
public:virtual ~AirTrafficControl() = default;/*** @brief 请求起飞* * @param flightId 航班号* @return bool 是否允许起飞*/virtual bool requestTakeoff(const std::string& flightId) = 0;/*** @brief 请求降落* * @param flightId 航班号* @return bool 是否允许降落*/virtual bool requestLanding(const std::string& flightId) = 0;/*** @brief 通知起飞完成* * @param flightId 航班号*/virtual void notifyTakeoffComplete(const std::string& flightId) = 0;/*** @brief 通知降落完成* * @param flightId 航班号*/virtual void notifyLandingComplete(const std::string& flightId) = 0;/*** @brief 注册飞机* * @param aircraft 飞机对象*/virtual void registerAircraft(std::shared_ptr<class Aircraft> aircraft) = 0;
};/*** @brief 飞机抽象类* * 定义飞机的基本行为和状态*/
class Aircraft {
protected:std::string flightId_;FlightStatus status_;std::shared_ptr<AirTrafficControl> atc_;public:Aircraft(const std::string& flightId, std::shared_ptr<AirTrafficControl> atc): flightId_(flightId), status_(FlightStatus::ON_GROUND), atc_(atc) {}virtual ~Aircraft() = default;std::string getFlightId() const { return flightId_; }FlightStatus getStatus() const { return status_; }/*** @brief 请求起飞*/virtual void requestTakeoff() {std::cout << "航班 " << flightId_ << " 请求起飞" << std::endl;if (atc_->requestTakeoff(flightId_)) {status_ = FlightStatus::TAKING_OFF;std::cout << "航班 " << flightId_ << " 开始起飞" << std::endl;} else {std::cout << "航班 " << flightId_ << " 起飞请求被拒绝" << std::endl;}}/*** @brief 请求降落*/virtual void requestLanding() {std::cout << "航班 " << flightId_ << " 请求降落" << std::endl;if (atc_->requestLanding(flightId_)) {status_ = FlightStatus::LANDING;std::cout << "航班 " << flightId_ << " 开始降落" << std::endl;} else {std::cout << "航班 " << flightId_ << " 降落请求被拒绝" << std::endl;}}/*** @brief 通知起飞完成*/virtual void notifyTakeoffComplete() {status_ = FlightStatus::IN_AIR;atc_->notifyTakeoffComplete(flightId_);std::cout << "航班 " << flightId_ << " 起飞完成,正在飞行" << std::endl;}/*** @brief 通知降落完成*/virtual void notifyLandingComplete() {status_ = FlightStatus::ON_GROUND;atc_->notifyLandingComplete(flightId_);std::cout << "航班 " << flightId_ << " 降落完成" << std::endl;}
};/*** @brief 具体飞机类*/
class CommercialAircraft : public Aircraft {
public:CommercialAircraft(const std::string& flightId, std::shared_ptr<AirTrafficControl> atc): Aircraft(flightId, atc) {}
};/*** @brief 具体航空管制中介者*/
class ConcreteATC : public AirTrafficControl {
private:std::vector<std::shared_ptr<Aircraft>> aircrafts_;int runwayInUse_;  // 跑道使用状态public:ConcreteATC() : runwayInUse_(-1) {}bool requestTakeoff(const std::string& flightId) override {// 检查跑道是否被占用if (runwayInUse_ != -1) {std::cout << "塔台回复 " << flightId << ": 跑道忙碌,请等待" << std::endl;return false;}// 分配跑道for (size_t i = 0; i < aircrafts_.size(); ++i) {if (aircrafts_[i]->getFlightId() == flightId) {runwayInUse_ = i;std::cout << "塔台回复 " << flightId << ": 允许起飞,使用跑道" << std::endl;return true;}}return false;}bool requestLanding(const std::string& flightId) override {// 检查跑道是否被占用if (runwayInUse_ != -1) {std::cout << "塔台回复 " << flightId << ": 跑道忙碌,请盘旋等待" << std::endl;return false;}// 分配跑道for (size_t i = 0; i < aircrafts_.size(); ++i) {if (aircrafts_[i]->getFlightId() == flightId) {runwayInUse_ = i;std::cout << "塔台回复 " << flightId << ": 允许降落,使用跑道" << std::endl;return true;}}return false;}void notifyTakeoffComplete(const std::string& flightId) override {std::cout << "塔台确认: " << flightId << " 起飞完成,释放跑道" << std::endl;runwayInUse_ = -1;}void notifyLandingComplete(const std::string& flightId) override {std::cout << "塔台确认: " << flightId << " 降落完成,释放跑道" << std::endl;runwayInUse_ = -1;}void registerAircraft(std::shared_ptr<Aircraft> aircraft) override {aircrafts_.push_back(aircraft);std::cout << "塔台: 注册航班 " << aircraft->getFlightId() << std::endl;}
};// 演示代码
int main() {// 创建航空管制中心auto atc = std::make_shared<ConcreteATC>();// 创建飞机auto flight1 = std::make_shared<CommercialAircraft>("CA123", atc);auto flight2 = std::make_shared<CommercialAircraft>("UA456", atc);auto flight3 = std::make_shared<CommercialAircraft>("DL789", atc);// 注册飞机atc->registerAircraft(flight1);atc->registerAircraft(flight2);atc->registerAircraft(flight3);std::cout << "\n=== 航空管制演示 ===\n" << std::endl;// 飞机操作flight1->requestTakeoff();  // 应该成功flight1->notifyTakeoffComplete();flight2->requestTakeoff();  // 应该成功flight3->requestLanding();  // 应该被拒绝(跑道忙碌)flight2->notifyTakeoffComplete();flight3->requestLanding();  // 现在应该成功return 0;
}

3.3 案例三:UI组件交互系统

场景描述
设计一个用户界面,包含多个交互组件(按钮、文本框、复选框等),这些组件之间的行为相互影响,但组件之间不直接通信,通过中介者协调。

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
#include <functional>// 前向声明
class UIComponent;/*** @brief UI中介者接口* * 协调UI组件之间的交互行为*/
class UIMediator {
public:virtual ~UIMediator() = default;/*** @brief 组件状态变化通知* * @param component 发生变化的组件* @param event 事件类型*/virtual void notify(std::shared_ptr<UIComponent> component, const std::string& event) = 0;/*** @brief 注册组件* * @param id 组件ID* @param component 组件对象*/virtual void registerComponent(const std::string& id, std::shared_ptr<UIComponent> component) = 0;
};/*** @brief UI组件抽象类*/
class UIComponent {
protected:std::string id_;bool enabled_;std::shared_ptr<UIMediator> mediator_;public:UIComponent(const std::string& id, std::shared_ptr<UIMediator> mediator): id_(id), enabled_(true), mediator_(mediator) {}virtual ~UIComponent() = default;std::string getId() const { return id_; }bool isEnabled() const { return enabled_; }virtual void setEnabled(bool enabled) {enabled_ = enabled;std::cout << "组件 " << id_ << " " << (enabled ? "启用" : "禁用") << std::endl;}/*** @brief 触发组件行为*/virtual void trigger() {if (enabled_) {std::cout << "组件 " << id_ << " 被触发" << std::endl;mediator_->notify(shared_from_this(), "triggered");}}/*** @brief 处理来自中介者的通知* * @param event 事件类型* @param data 事件数据*/virtual void handleEvent(const std::string& event, const std::string& data = "") = 0;
};/*** @brief 按钮组件*/
class Button : public UIComponent, public std::enable_shared_from_this<Button> {
public:Button(const std::string& id, std::shared_ptr<UIMediator> mediator): UIComponent(id, mediator) {}void handleEvent(const std::string& event, const std::string& data = "") override {if (event == "disable_buttons") {setEnabled(false);} else if (event == "enable_buttons") {setEnabled(true);}}
};/*** @brief 文本框组件*/
class TextBox : public UIComponent, public std::enable_shared_from_this<TextBox> {
private:std::string text_;public:TextBox(const std::string& id, std::shared_ptr<UIMediator> mediator): UIComponent(id, mediator), text_("") {}void setText(const std::string& text) {text_ = text;std::cout << "文本框 " << id_ << " 内容设置为: " << text << std::endl;mediator_->notify(shared_from_this(), "text_changed");}std::string getText() const { return text_; }void handleEvent(const std::string& event, const std::string& data = "") override {if (event == "clear_text") {setText("");} else if (event == "disable_input") {setEnabled(false);}}
};/*** @brief 复选框组件*/
class CheckBox : public UIComponent, public std::enable_shared_from_this<CheckBox> {
private:bool checked_;public:CheckBox(const std::string& id, std::shared_ptr<UIMediator> mediator): UIComponent(id, mediator), checked_(false) {}void setChecked(bool checked) {checked_ = checked;std::cout << "复选框 " << id_ << " " << (checked ? "选中" : "取消选中") << std::endl;mediator_->notify(shared_from_this(), "state_changed");}bool isChecked() const { return checked_; }void trigger() override {if (enabled_) {setChecked(!checked_);}}void handleEvent(const std::string& event, const std::string& data = "") override {// 复选框对其他组件事件不敏感}
};/*** @brief 具体UI中介者*/
class ConcreteUIMediator : public UIMediator {
private:std::unordered_map<std::string, std::shared_ptr<UIComponent>> components_;public:void notify(std::shared_ptr<UIComponent> component, const std::string& event) override {std::string componentId = component->getId();if (componentId == "submit_btn" && event == "triggered") {// 提交按钮被点击:禁用所有按钮,清空文本框for (auto& pair : components_) {if (pair.first.find("btn") != std::string::npos) {pair.second->handleEvent("disable_buttons");} else if (pair.first.find("textbox") != std::string::npos) {pair.second->handleEvent("clear_text");}}} else if (componentId == "agree_checkbox" && event == "state_changed") {// 同意复选框状态变化:启用/禁用提交按钮auto checkbox = std::dynamic_pointer_cast<CheckBox>(component);if (checkbox) {auto submitBtn = components_["submit_btn"];if (submitBtn) {submitBtn->setEnabled(checkbox->isChecked());}}} else if (componentId == "name_textbox" && event == "text_changed") {// 姓名文本框内容变化:检查是否可以启用提交按钮auto textbox = std::dynamic_pointer_cast<TextBox>(component);if (textbox) {auto agreeCheckbox = components_["agree_checkbox"];auto submitBtn = components_["submit_btn"];if (agreeCheckbox && submitBtn) {bool agreed = std::dynamic_pointer_cast<CheckBox>(agreeCheckbox)->isChecked();bool hasName = !textbox->getText().empty();submitBtn->setEnabled(agreed && hasName);}}}}void registerComponent(const std::string& id, std::shared_ptr<UIComponent> component) override {components_[id] = component;std::cout << "注册UI组件: " << id << std::endl;}
};// 演示代码
int main() {// 创建UI中介者auto mediator = std::make_shared<ConcreteUIMediator>();// 创建UI组件auto nameTextbox = std::make_shared<TextBox>("name_textbox", mediator);auto agreeCheckbox = std::make_shared<CheckBox>("agree_checkbox", mediator);auto submitButton = std::make_shared<Button>("submit_btn", mediator);// 注册组件mediator->registerComponent("name_textbox", nameTextbox);mediator->registerComponent("agree_checkbox", agreeCheckbox);mediator->registerComponent("submit_btn", submitButton);std::cout << "\n=== UI交互演示 ===\n" << std::endl;// 模拟用户交互std::cout << "1. 初始状态 - 提交按钮应该被禁用" << std::endl;std::cout << "提交按钮状态: " << (submitButton->isEnabled() ? "启用" : "禁用") << std::endl;std::cout << "\n2. 输入姓名 - 提交按钮仍然被禁用(未同意条款)" << std::endl;nameTextbox->setText("张三");std::cout << "提交按钮状态: " << (submitButton->isEnabled() ? "启用" : "禁用") << std::endl;std::cout << "\n3. 同意条款 - 提交按钮应该启用" << std::endl;agreeCheckbox->trigger();  // 选中复选框std::cout << "提交按钮状态: " << (submitButton->isEnabled() ? "启用" : "禁用") << std::endl;std::cout << "\n4. 点击提交按钮 - 所有按钮被禁用,文本框被清空" << std::endl;submitButton->trigger();return 0;
}

4. 编译与运行

4.1 Makefile范例

# 编译器设置
CXX := g++
CXXFLAGS := -std=c++17 -Wall -Wextra -O2
TARGET := mediator_demo
SRCS := chat_mediator.cpp aircraft_mediator.cpp ui_mediator.cpp# 默认目标
all: $(TARGET)# 链接目标文件
$(TARGET): $(SRCS:.cpp=.o)$(CXX) $(CXXFLAGS) -o $@ $^# 编译源文件
%.o: %.cpp$(CXX) $(CXXFLAGS) -c $< -o $@# 清理生成文件
clean:rm -f *.o $(TARGET)# 运行演示
run: $(TARGET)./$(TARGET)# 调试编译
debug: CXXFLAGS += -g -DDEBUG
debug: $(TARGET).PHONY: all clean run debug

4.2 编译方法

# 1. 基础编译
make# 2. 调试模式编译
make debug# 3. 单独编译聊天室案例
g++ -std=c++17 -o chat_demo chat_mediator.cpp# 4. 清理编译文件
make clean

4.3 运行结果解读

聊天室系统输出示例

=== 聊天开始 ===Alice 发送广播: 大家好!
=== 聊天室广播 === (Alice): 大家好!
Bob 收到来自 Alice 的消息: 大家好!
Charlie 收到来自 Alice 的消息: 大家好!Alice 私聊 Bob: 嘿,Bob,有个秘密要告诉你
=== 私聊消息 === [Alice -> Bob]: 嘿,Bob,有个秘密要告诉你
Bob 收到来自 Alice 的消息: [私聊] 嘿,Bob,有个秘密要告诉你

结果分析

  • 消息通过中介者正确路由到目标用户
  • 广播消息发送给除发送者外的所有用户
  • 私聊消息只发送给指定用户
  • 系统消息(用户加入/离开)自动广播

5. 模式优势与局限性总结

5.1 优势对比

方面使用中介者模式前使用中介者模式后
耦合度对象间直接引用,网状耦合通过中介者通信,星状耦合
可维护性修改一个对象影响多个对象交互逻辑集中,易于维护
扩展性新增对象需要修改多个现有对象新增对象只需注册到中介者
复用性对象因相互引用难以单独复用对象可以独立复用

5.2 适用场景建议

推荐使用中介者模式

  • 🎯 对象间交互复杂且频繁
  • 🎯 需要集中管理对象间关系
  • 🎯 系统需要良好的扩展性和维护性

不推荐使用中介者模式

  • ⚠️ 对象间交互简单直接
  • ⚠️ 性能要求极高的场景
  • ⚠️ 中介者可能成为系统瓶颈

中介者模式通过引入协调层,成功地将复杂的网状交互转化为清晰的星状结构,是现代软件设计中解决对象通信复杂性的重要工具。

http://www.dtcms.com/a/422594.html

相关文章:

  • 小程序原创--基于微信开发者工具实现的猜谜游戏程序
  • 如何进行WGBS的数据挖掘——从甲基化水平到功能通路
  • C# 23种设计模式详解与示例
  • 以创新技术解决客户痛点 在细分领域铸就核心竞争力新天力叩响资本市场大门
  • 14.单臂路由(2025年9月29日)
  • 湖南网站建设平台配置asp网站
  • 计育韬:基于AI的数据可视化设计入门工作流
  • 手势检测(充满科技感)
  • 大模型的第一性考虑:从信息论、计算理论与物理约束的视角
  • MySQL备份策略核心知识点总结
  • 企业微信-智能表格介绍
  • 2025 AI 落地图谱:从技术突破到产业重构的变革之路
  • [pytest] 一文掌握 fixture 的作用域(scope)机制
  • MVC HTML 帮助器
  • Android -Glide实战技术总结
  • 信息展示网站怎么做能够让网站流量大
  • Linux 系统 IO 编程入门:从文件操作到硬件设备访问
  • 以CodeBuddy Code为砚,Prompt为丹青,勾勒编程星河
  • 房产网站模板程序wordpress去版权
  • OpenCV 摄像头参数控制详解
  • Kimi-Audio:Kimi开源的通用音频基础模型,支持语音识别、音频理解等多种任务
  • 阿里开源视频修复方法Vivid-VR:以独特策略与架构革新,引领生成视频修复高质量可控新时代。
  • 独立开发在线客服系统手记:实现对 PostgreSQL 的支持,以及与 MySQL 的对比
  • 【项目】Vision Master OpenCV 3.0 版本(预)发行说明
  • 官方网站是什么意思网站备案 godaddy
  • 温州网站运营长沙网页制作模板
  • 前端埋点(打点)方案
  • pako处理 urlencode(gzcompress(json_encode($res))) php的加密方式web解析
  • 深入理解 SSE:服务器发送事件及其在前后端中的实践
  • Web典型路由结构之Next.js (App Router, v13+) )(文件系统驱动的路由:File-based Routing)声明式路由:文件即路由