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

如何设计文本格式化对象以实现多状态多模式的多样化打印

嘿,这个需求其实可以通过策略模式结合枚举状态来优雅实现,既满足不同格式的扩展性,又能清晰关联Mode和State的逻辑。我给你捋捋具体的设计思路和代码实现:

核心思路

我们把「格式化逻辑」和「状态/模式管理」拆分开:

  1. 定义格式化策略基类,每种输出格式对应一个策略子类
  2. Formatter类负责管理当前的Mode、State和数据字段,并根据状态组合自动选择对应的格式化策略
  3. 重载operator<<让Formatter可以直接输出到流,符合C++的IO风格

具体代码实现

首先修正并完善枚举定义(用enum class更安全,避免隐式转换):

#include <iostream>
#include <vector>
#include <string>
#include <memory>

// 模式枚举
enum class Mode { mode1 = 0, mode2 };
// 状态枚举
enum class State { state1 = 0, state2 };

// 存储单个键值对的结构体
struct DataField {
    std::string name;
    std::string value;
};

接下来定义格式化策略的抽象基类:

// 格式化策略基类:所有格式都要实现这个接口
class FormatStrategy {
public:
    virtual ~FormatStrategy() = default;
    // 核心方法:接收输出流、数据字段、当前模式和状态,完成格式化输出
    virtual void format(std::ostream& os, const std::vector<DataField>& fields, Mode mode, State state) const = 0;
};

然后为三种需求格式实现具体的策略类:

// 策略1:name1 value1 name2 value2 ... 格式
class KeyValuePairStrategy : public FormatStrategy {
public:
    void format(std::ostream& os, const std::vector<DataField>& fields, Mode mode, State state) const override {
        for (size_t i = 0; i < fields.size(); ++i) {
            if (i > 0) os << " ";
            os << fields[i].name << " " << fields[i].value;
        }
        // 可以根据模式/状态做额外调整,比如mode2时自动换行
        if (mode == Mode::mode2) os << "\n";
    }
};

// 策略2:只输出值,value1 value2 value3 格式
class ValueOnlyStrategy : public FormatStrategy {
public:
    void format(std::ostream& os, const std::vector<DataField>& fields, Mode mode, State state) const override {
        for (size_t i = 0; i < fields.size(); ++i) {
            if (i > 0) os << " ";
            os << fields[i].value;
        }
        // 示例:state2时末尾加逗号
        if (state == State::state2) os << ",";
    }
};

// 策略3:name1 : value1. name2 : value2 ... 格式
class ColonKeyValueStrategy : public FormatStrategy {
public:
    void format(std::ostream& os, const std::vector<DataField>& fields, Mode mode, State state) const override {
        for (size_t i = 0; i < fields.size(); ++i) {
            if (i > 0) os << " ";
            os << fields[i].name << " : " << fields[i].value;
            // 按照示例,第一个字段后加句号
            if (i == 0) os << ".";
        }
    }
};

最后实现Formatter类,负责状态管理和策略选择:

class Formatter {
private:
    std::unique_ptr<FormatStrategy> strategy_; // 当前使用的格式化策略
    Mode mode_;
    State state_;
    std::vector<DataField> fields_; // 存储所有要打印的键值对

    // 根据当前mode和state自动选择对应的策略(这里可以自定义映射逻辑)
    void selectStrategy() {
        // 示例映射规则:你可以根据实际需求修改
        if (mode_ == Mode::mode1) {
            strategy_ = std::make_unique<KeyValuePairStrategy>();
        } else if (mode_ == Mode::mode2 && state_ == State::state1) {
            strategy_ = std::make_unique<ValueOnlyStrategy>();
        } else if (mode_ == Mode::mode2 && state_ == State::state2) {
            strategy_ = std::make_unique<ColonKeyValueStrategy>();
        } else {
            // 默认策略,防止未覆盖的状态组合
            strategy_ = std::make_unique<KeyValuePairStrategy>();
        }
    }

public:
    // 构造函数:初始化模式、状态和数据字段
    Formatter(Mode mode, State state, std::vector<DataField> fields)
        : mode_(mode), state_(state), fields_(std::move(fields)) {
        selectStrategy();
    }

    // 动态修改模式,自动切换策略
    void setMode(Mode mode) {
        mode_ = mode;
        selectStrategy();
    }

    // 动态修改状态,自动切换策略
    void setState(State state) {
        state_ = state;
        selectStrategy();
    }

    // 添加新的键值对
    void addField(const DataField& field) {
        fields_.push_back(field);
    }

    // 重载ostream运算符,支持直接输出Formatter对象
    friend std::ostream& operator<<(std::ostream& os, const Formatter& formatter) {
        formatter.strategy_->format(os, formatter.fields_, formatter.mode_, formatter.state_);
        return os;
    }

    // 快捷打印方法,直接输出到cout
    void print() const {
        std::cout << *this << std::endl;
    }
};

使用示例

int main() {
    // 准备测试数据
    std::vector<DataField> testFields = {
        {"name1", "value1"},
        {"name2", "value2"},
        {"name3", "value3"}
    };

    // 测试mode1 + state1
    Formatter fmt(Mode::mode1, State::state1, testFields);
    std::cout << "Mode1 + State1 输出:" << fmt << "\n\n";

    // 切换到mode2 + state1
    fmt.setMode(Mode::mode2);
    fmt.setState(State::state1);
    std::cout << "Mode2 + State1 输出:" << fmt << "\n\n";

    // 切换到mode2 + state2
    fmt.setState(State::state2);
    std::cout << "Mode2 + State2 输出:" << fmt << "\n";

    return 0;
}

设计优势与扩展建议

  • 扩展性极强:以后要加新格式?只需要新增一个FormatStrategy的子类,修改selectStrategy里的映射规则即可,完全不用改动原有代码(符合开闭原则)
  • 职责清晰:策略类只负责格式生成,Formatter只负责状态和数据管理,逻辑不混乱
  • 灵活性高:可以动态切换Mode和State,自动适配格式;也可以随时添加新的键值对
  • 可选优化:可以把策略对象做成单例,避免重复创建;或者允许外部传入自定义策略,进一步提升灵活性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:50:59