以下是基于工厂模式的设计和实现,分为三部分:Link 类、RTA 类、工厂类。
1. Link 类
Link
是一个封装底层通信逻辑的类,支持发送、接收、以及广播功能。
#include <asio2/udp/udp_server.hpp>
#include <string>
#include <functional>
#include <memory>class Link {
public:using RecvCallback = std::function<void(const std::string& data, const std::string& clientAddress, uint16_t clientPort)>;Link() : server_() {// 设置广播选项server_.bind_init([this]() {asio2::error_code ec;server_.acceptor().set_option(asio::socket_base::broadcast(true), ec);if (ec) {std::cerr << "Failed to enable broadcast: " << ec.message() << std::endl;}});}// 启动通信void start(const std::string& host, const std::string& port) {server_.bind_recv([this](std::shared_ptr<asio2::udp_session>& session_ptr, std::string_view data) {if (recvCallback_) {recvCallback_(std::string(data), session_ptr->remote_address(), session_ptr->remote_port());}});if (!server_.start(host, port, asio2::use_kcp)) {std::cerr << "Failed to start Link: " << asio2::last_error_msg() << std::endl;} else {std::cout << "Link started on " << host << ":" << port << std::endl;}}// 停止通信void stop() {server_.stop();}// 设置接收数据的回调函数void setRecvCallback(RecvCallback callback) {recvCallback_ = std::move(callback);}// 广播数据void broadcast(const std::string& data, const std::string& broadcastAddress, const std::string& port) {server_.async_send_to(data, broadcastAddress, port, [](asio2::error_code ec, std::size_t bytes_sent) {if (ec) {std::cerr << "Broadcast failed: " << ec.message() << std::endl;} else {std::cout << "Broadcast success: " << bytes_sent << " bytes sent" << std::endl;}});}// 发送数据给指定的客户端void sendTo(const std::string& data, const std::string& clientAddress, const std::string& port) {server_.async_send_to(data, clientAddress, port, [](asio2::error_code ec, std::size_t bytes_sent) {if (ec) {std::cerr << "Send failed: " << ec.message() << std::endl;}});}private:asio2::udp_server server_;RecvCallback recvCallback_; // 数据接收回调
};
2. RTA 类
RTA
类依赖于 Link
,用来完成具体的业务逻辑。Link
是通过依赖注入的方式传入的。
#include <iostream>
#include <memory>
#include <string>class RTA {
public:explicit RTA(std::shared_ptr<Link> link) : link_(std::move(link)) {// 设置接收数据的回调link_->setRecvCallback([this](const std::string& data, const std::string& clientAddress, uint16_t clientPort) {this->onReceive(data, clientAddress, clientPort);});}// 启动 RTA 的功能void start(const std::string& host, const std::string& port) {link_->start(host, port);}// 停止 RTA 的功能void stop() {link_->stop();}// 业务逻辑:处理接收到的数据void onReceive(const std::string& data, const std::string& clientAddress, uint16_t clientPort) {std::cout << "RTA received data: " << data << " from " << clientAddress << ":" << clientPort << std::endl;// 示例:发送回显数据link_->sendTo("Echo: " + data, clientAddress, std::to_string(clientPort));}private:std::shared_ptr<Link> link_; // 底层通信 Link
};
3. 工厂类
工厂类负责创建 Link
和 RTA
对象,并确保它们之间的依赖关系。
#include <memory>class Factory {
public:// 创建 Link 对象static std::shared_ptr<Link> createLink() {return std::make_shared<Link>();}// 创建 RTA 对象static std::unique_ptr<RTA> createRTA(std::shared_ptr<Link> link) {return std::make_unique<RTA>(std::move(link));}
};
4. 使用工厂类
以下是使用工厂类创建 Link
和 RTA
对象的示例:
int main() {// 通过工厂创建 Link 对象std::shared_ptr<Link> link = Factory::createLink();// 通过工厂创建 RTA 对象,并注入 Linkstd::unique_ptr<RTA> rta = Factory::createRTA(link);// 启动 RTA(同时启动底层通信 Link)rta->start("0.0.0.0", "8035");std::cout << "Press Enter to exit..." << std::endl;std::cin.get();// 停止 RTA(同时停止底层通信 Link)rta->stop();return 0;
}
5. 代码运行逻辑
-
工厂创建
Link
和RTA
:Link
负责底层 UDP 通信,包含发送、接收和广播功能。RTA
依赖于Link
,并通过Link
完成业务逻辑。
-
启动 RTA:
- 调用
rta->start()
会启动Link
,并设置数据接收的回调。
- 调用
-
处理接收数据:
Link
收到数据后,会调用注册的回调,将数据传递给RTA
的onReceive
方法。
-
发送或广播数据:
RTA
使用Link
提供的sendTo
或broadcast
方法发送数据。
6. 优势
- 模块化:
Link
专注于通信逻辑,而RTA
专注于业务逻辑。 - 可扩展: 如果需要支持新的通信方式(如 TCP 或 WebSocket),只需扩展
Link
类,而无需修改RTA
。 - 解耦: 工厂模式将对象的创建和使用分离,方便统一管理依赖关系。
总结
通过工厂模式封装底层通信(Link
)和业务逻辑(RTA
),可以实现高内聚、低耦合的设计:
Link
提供底层通信能力,包括 UDP 收发和广播。RTA
使用Link
提供的功能来实现自己的业务逻辑。- 工厂类统一管理对象的创建和依赖关系。