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

C++中策略与建造者模式及模板的设计问题咨询

C++策略+建造者模式几何对象方案问题解决与设计分析

一、模板参数导致的成员存储与setStrategy方法问题解决

核心思路是用类型擦除消除模板参数对建造者类的耦合:

  1. 重构策略接口:将带模板的objreader_strategy改为非模板抽象基类,定义通用的解析操作纯虚函数,参数直接关联geometry对象:
class objreader_strategy {
public:
    virtual ~objreader_strategy() = default;
    virtual void process_vertex(const std::string& line, geometry& geo) = 0;
    virtual void process_face(const std::string& line, geometry& geo) = 0;
    // 按需添加其他解析方法(如法向量、纹理坐标)
};
  1. 调整模板策略子类:让vec_strategy<T, L, S>继承上述基类,在实现中处理模板类型对应的解析逻辑:
template<typename T, size_t L, size_t S>
class vec_strategy : public objreader_strategy {
public:
    void process_vertex(const std::string& line, geometry& geo) override {
        // 基于T(数据类型)、L(顶点维度)解析顶点并写入geo
    }
    void process_face(const std::string& line, geometry& geo) override {
        // 基于S(面的顶点数)解析面数据并写入geo
    }
};
  1. 修改建造者类:在geometry_obj中存储基类智能指针作为策略成员,实现通用的setStrategy方法:
class geometry_obj : public geometry_creator {
private:
    std::unique_ptr<objreader_strategy> current_strategy;
    geometry target_geo;
public:
    void setStrategy(std::unique_ptr<objreader_strategy> strategy) {
        current_strategy = std::move(strategy);
    }

    void read_obj_file(const std::string& file_path) {
        if (!current_strategy) return;
        std::ifstream obj_file(file_path);
        std::string line;
        while (std::getline(obj_file, line)) {
            if (line.starts_with("v ")) {
                current_strategy->process_vertex(line, target_geo);
            } else if (line.starts_with("f ")) {
                current_strategy->process_face(line, target_geo);
            }
            // 其他行类型处理
        }
    }

    geometry get_result() override {
        return std::move(target_geo);
    }
};

外部调用时只需创建具体策略实例传入:

auto strategy = std::make_unique<vec_strategy<float, 3, 3>>();
geometry_obj builder;
builder.setStrategy(std::move(strategy));
builder.read_obj_file("model.obj");
auto final_geo = builder.get_result();

二、避免多实例化vec_strategy,复用单一成员

上述方案天然支持单一策略成员复用:geometry_obj中的current_strategy是唯一的策略实例,所有解析操作都会复用它,无需每次调用方法时创建新对象。

如果策略是无状态的(不需要存储实例级数据),可以进一步用单例模式避免重复创建:

template<typename T, size_t L, size_t S>
class vec_strategy : public objreader_strategy {
public:
    static std::shared_ptr<vec_strategy> instance() {
        static auto inst = std::make_shared<vec_strategy>();
        return inst;
    }

    // 禁止拷贝和赋值,确保单例唯一性
    vec_strategy(const vec_strategy&) = delete;
    vec_strategy& operator=(const vec_strategy&) = delete;
private:
    vec_strategy() = default;
};

调用时直接传入单例指针:

builder.setStrategy(vec_strategy<float, 3, 3>::instance());

三、当前设计合理性分析

优点

  1. 模式适配性:策略模式封装不同解析规则(数据类型、顶点维度等),建造者模式管控几何对象的构建流程,两者解耦,符合单一职责原则。
  2. 扩展性:新增解析策略只需实现objreader_strategy子类;新增几何对象建造源(如JSON、二进制文件)只需继承geometry_creator,完全符合开闭原则。
  3. 可测试性:抽象接口便于单元测试——可以模拟策略实现测试建造流程,也可单独测试策略的解析逻辑,无需依赖完整文件IO。

潜在优化点

  1. 类型安全:需确保geometry类能兼容策略的模板类型(比如用多态容器、std::variant存储不同类型的顶点/面数据),避免类型不匹配导致的错误。
  2. 模板耦合简化:如果geometry本身是强类型的(仅支持固定数据类型的顶点),可考虑将geometry和策略的模板参数绑定,进一步提升类型安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:55:18