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

图表类代码重构:样式提取后的设计问题及优化咨询

图表类结构重构的优化方案

原始类结构

class ChartBase {
private:
   int transparency; //chart attribute
};
class XYChart : public ChartBase{
private:
  std::string xAxis;
  std::string yAxis;
};
class LineChart : public XYChart
{
private:
  int lineWidth;
  int lineColor;
};

重构后的类结构

class StyleBase {
private:
  int transparency;
};
class XYStyle : public StyleBase {
private:
  std::string xAxis;
  std::string yAxis;
};
class LineStyle : public XYStyle {
private:
  int lineWidth;
  int lineColor;
};

class ChartBase {
protected:
  std::shared_ptr<StyleBase> style;
};

当前设计存在的问题

  • 派生类(如LineChart)需要将style指针强制转换为对应Style类型才能访问专属属性,类型不安全且代码繁琐。
  • 每个Chart派生类必须在构造函数中替换style实例,基类ChartBase中创建StyleBase的操作完全冗余,但XYChart的构造逻辑又必须保留(存在直接使用XYChart的场景)。

优化方案1:模板基类实现强类型Style访问

让ChartBase成为模板类,绑定对应的Style类型,派生类可直接获取强类型的Style引用,彻底避免强制转换:

// 定义抽象基类保证图表类的多态性(如果需要多态场景)
class AbstractChart {
public:
    virtual ~AbstractChart() = default;
    virtual void draw() = 0;
};

template<typename TStyle>
class ChartBase : public AbstractChart {
protected:
    std::shared_ptr<TStyle> style;
public:
    ChartBase() : style(std::make_shared<TStyle>()) {}
};

class XYChart : public ChartBase<XYStyle> {
public:
    void draw() override {
        // 直接访问 style->xAxis、style->yAxis,无需转换
    }
};

class LineChart : public ChartBase<LineStyle> {
public:
    void draw() override {
        // 直接访问 style->lineWidth、style->lineColor,无需转换
    }
};

如果不需要多态,可以去掉AbstractChart,直接让派生类继承对应模板基类即可。

优化方案2:构造函数注入Style实例

让ChartBase通过构造函数接收Style实例,派生类根据需求传入对应类型的Style,消除基类的冗余构造:

class ChartBase {
protected:
    std::shared_ptr<StyleBase> style;
public:
    explicit ChartBase(std::shared_ptr<StyleBase> s) : style(std::move(s)) {}
};

class XYChart : public ChartBase {
public:
    XYChart() : ChartBase(std::make_shared<XYStyle>()) {}
    // 支持外部传入自定义XYStyle的重载构造
    explicit XYChart(std::shared_ptr<XYStyle> s) : ChartBase(std::move(s)) {}
};

class LineChart : public ChartBase {
public:
    LineChart() : ChartBase(std::make_shared<LineStyle>()) {}
    // 支持外部传入自定义LineStyle的重载构造
    explicit LineChart(std::shared_ptr<LineStyle> s) : ChartBase(std::move(s)) {}

private:
    // 内部提供类型安全的Style访问方法,避免外部强制转换
    LineStyle* getLineStyle() {
        auto ptr = std::dynamic_pointer_cast<LineStyle>(style);
        if (!ptr) {
            throw std::runtime_error("Invalid style type for LineChart");
        }
        return ptr.get();
    }

public:
    // 对外提供类型安全的属性操作接口
    void setLineWidth(int width) {
        getLineStyle()->lineWidth = width;
    }
};

是否应该提取属性到Style类?

提取属性到独立的Style类是合理的,尤其适合以下场景:

  • 需要为同一个图表实例切换不同样式配置。
  • 多个图表实例需要共享相同样式配置(通过shared_ptr可轻松实现)。
  • 样式配置需要独立于图表逻辑进行复用、序列化或单独维护。

如果业务中没有上述需求,只是单纯拆分代码,原始结构可能更简洁;但如果有上述场景,当前的拆分方向正确,只需通过上述方案优化现有问题即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:32:07