You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何选择可抽象多源IO操作的输入数据处理设计模式

适配方案:使用策略模式

策略模式可以把不同数据源的读写操作封装成独立的策略类,所有策略类都实现同一个抽象接口,上层的文本处理逻辑只和抽象接口交互,不需要感知底层是文件、管道还是套接字,完美适配你现在需要扩展多数据源的需求。如果后续需要新增其他类型的数据源,只需要新增对应策略实现即可,不需要修改原有处理逻辑,符合开闭原则。


实现示例

第一步:定义抽象数据源接口

所有数据源都要实现该接口的核心操作,上层逻辑仅依赖该抽象接口:

#include <string>
#include <stdexcept>

// 抽象数据源策略接口
class DataSource {
public:
    virtual ~DataSource() = default;
    // 打开数据源,参数为对应资源的标识(文件路径/管道名/套接字地址等)
    virtual void open(const std::string& resource) = 0;
    // 读取一行内容,返回值表示是否还有更多内容可读
    virtual bool readLine(std::string& line) = 0;
    // 关闭数据源
    virtual void close() = 0;
    // 判断数据源是否处于可用状态
    virtual bool isValid() const = 0;
};

第二步:实现文件数据源策略类

适配你原有文件读取的逻辑:

#include <fstream>

class FileDataSource : public DataSource {
private:
    std::ifstream file;
public:
    void open(const std::string& filePath) override {
        file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        file.open(filePath);
    }

    bool readLine(std::string& line) override {
        if (file.peek() == EOF) {
            return false;
        }
        std::getline(file, line);
        return true;
    }

    void close() override {
        if (file.is_open()) {
            file.close();
        }
    }

    bool isValid() const override {
        return file.is_open();
    }
};

第三步:扩展管道数据源实现示例

新增其他数据源仅需要实现抽象接口即可,原有处理逻辑无需修改:

#include <fcntl.h>
#include <unistd.h>

class PipeDataSource : public DataSource {
private:
    int pipeFd = -1;
    static const size_t BUF_SIZE = 1024;
public:
    void open(const std::string& pipeName) override {
        pipeFd = ::open(pipeName.c_str(), O_RDONLY);
        if (pipeFd < 0) {
            throw std::runtime_error("Failed to open pipe");
        }
    }

    bool readLine(std::string& line) override {
        // 此处为简化的按行读取示例,生产环境可自行完善换行判断逻辑
        char buf[BUF_SIZE];
        ssize_t len = ::read(pipeFd, buf, BUF_SIZE - 1);
        if (len <= 0) return false;
        buf[len] = '\0';
        line = buf;
        return true;
    }

    void close() override {
        if (pipeFd >= 0) {
            ::close(pipeFd);
            pipeFd = -1;
        }
    }

    bool isValid() const override {
        return pipeFd >= 0;
    }
};

第四步:上层统一处理逻辑

完全不依赖具体的数据源类型,所有数据源都可以复用该处理逻辑:

#include <iostream>

void processDataSource(DataSource& source, const std::string& resource) {
    try {
        source.open(resource);
        if (source.isValid()) {
            std::string line;
            while (source.readLine(line)) {
                // 原有行处理逻辑完全不需要修改,直接复用即可
                // process line here
            }
            source.close();
        }
    } catch (const std::exception& e) {
        std::cout << "Processing error: " << e.what() << std::endl;
        return;
    } catch (...) {
        std::cout << "Unknown error occurred" << std::endl;
    }
}

使用示例

int main() {
    // 处理文本文件
    FileDataSource fileSource;
    processDataSource(fileSource, "test.txt");

    // 处理管道
    PipeDataSource pipeSource;
    processDataSource(pipeSource, "/tmp/test.pipe");

    // 后续扩展套接字仅需要新增SocketDataSource实现类即可直接调用
    // SocketDataSource socketSource;
    // processDataSource(socketSource, "127.0.0.1:8080");
    return 0;
}

扩展说明

如果需要根据配置动态生成不同类型的数据源实例,可以搭配工厂模式封装数据源的创建逻辑,上层仅需要传入数据源类型即可拿到对应实例,进一步降低耦合。

内容的提问来源于stack exchange,提问作者AreaOfGreenNoise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 09:48:03