首页 > 解决方案 > 在 c++ 中初始化具有许多不可更改成员的更复杂的类构造的最佳方法是什么

问题描述

我目前正在设计应该代表混乱存储系统的类。

假设我们在具有某些属性的行和列中有插槽。因此,插槽在最小/最大高度、宽度、长度、重量等方面有不同的限制,这些限制来自参数文件。此外,插槽具有最大总重量,必须在将新包裹添加到该插槽之前检查该最大总重量。并且一排槽可以容纳的最大权重低于单个槽的最大权重之和。因此,例如每个单独的插槽可能能够容纳 50 公斤,但 10 个插槽的行不得超过 200 公斤,因此不允许每个插槽 100% 填充。对于最大权重低于单行的各个权重之和的列也是如此。row_id 和 column_id 是用于在物理系统中使用条形码或读取用于定位的任何内容对插槽进行寻址的数字。

由于所有这些参数在程序的生命周期内都不会改变,我的目的是设计类,使这些属性可以被 getter 函数读取,但对象中不应该有任何 setter 函数(甚至可能不是私有的) o 这些值不能被意外更改。

有一个类/函数可以读取配置文件并为带有插槽的行和列生成数据结构。这个函数应该能够读取配置并为每个包含一行插槽的列创建对象,并将配置中的所有值传递到插槽。

稍后当程序运行时,我还需要一些方法来搜索最佳匹配槽以添加下一个包裹或搜索包裹并按特定顺序卸载它们。

所以类的(简化的)基本结构是这样的:

Class Parcel {
  int width;
  int height;
  int length;
  int weight;
}

Class Slot {
  vector<Parcel> parcel;

  int min_width;
  int max_width;
  int min_height;
  int max_height;
  int min_length;
  int max_length;

  int max_total_weight;
  int act_total_weight;
  int total_length;
  int free_length;
}

Class Row {
  vector<Slot> slot;

  int row_id;
  int max_total_weight;
  int act_total_weight;
}

Class Column {
  vector<Row> row;

  int column_id;    
  int max_total_weight;
  int act_total_weight;
}

Class Storage {
  vector<Column> column;
}

所以这里是我关于如何初始化数据结构的想法:

第一种可能性是在类的构造函数中传递所有属性,但是构造函数有一些专门用于具有很多属性的 Slot 类的巨大参数列表。

我想到的第二件事(也是目前我最喜欢的方式)是使用包含所有参数的配置数据结构。此参数对象由配置函数填充并在初始化类时传递给构造函数。那么使用参数类而不是在存储类中再次定义所有参数也可能很有用。

第三种方法是使用私有 setter 和 public getter,并使配置类与数据结构类成为朋友,以便能够访问 setter 函数(但我更希望在最终的存储结构类中根本没有 setter。

我正在考虑的第四种方法是从包含 setter 函数的结构类中派生子类(以及创建数据结构所需的一些其他逻辑),因此子类没有自己的变量,而只有附加函数。因此子类用于填充属性,但基类被添加到数据结构向量中。

我还想使用工厂模式来初始化数据结构,因为对象通常具有相似或略有不同的属性。因此,在创建一排插槽后的第二种方法中,我可能想要更改该行中插槽的最大重量。因此,我需要更改工厂中的设置,然后工厂以不同方式填充参数数据结构并将其传递给 Slot 类。还是直接将数据结构传递给工厂并由工厂分配它更好,但我认为这不是工厂模式的本意。

我不知道这是否是一个好的方法,或者以上哪一个是最佳实践。或者我错过了什么,有一种更方便的解决方案吗?

谢谢(如果问题可能不是应该的方式,对不起)

标签: c++design-patternsfactory-patternclass-design

解决方案


在按照您的描述构建类时,您可以查看创建设计模式

您提出的第二个解决方案几乎是一种构建器设计模式。这将帮助您构建 Slot,例如分段。

举个例子:

#include <iostream>

class Slot {
  public:
  
  int GetMinWidth() const { return min_width_; };
  int GetMaxWidth() const { return max_width_; };
  
  // Builder class
  class SlotBuilder {
    public:
    
     SlotBuilder& SetMinWidth(int min_width) {
       min_width_ = min_width;
       return *this;
     }
     
     SlotBuilder& SetMaxWidth(int max_width) {
       max_width_ = max_width;
       return *this;
     }
     
     Slot Build() {
       return Slot(min_width_, max_width_);
     }
    
    private:
    int min_width_{/* you can add default value here*/};
    int max_width_{/* you can add default value here*/};
  };
  
  
  // This is optional, but creates a neat interface
  static SlotBuilder Create() {
    static SlotBuilder slot_builder;
    return slot_builder;
  }
  
  private:
  // Make constructor private to restrict access and force the use of the builder
  Slot(int min_width, int max_width) : min_width_(min_width), max_width_(max_width) {}

  const int min_width_;
  const int max_width_;
  // .
  // .
  // Continue with your const attributes
};

int main() {
    // Create the slot with the builder
    Slot slot = Slot::Create()
                .SetMinWidth(10)
                .SetMaxWidth(20)
                .Build();
    std::cout << slot.GetMinWidth() << ", " << slot.GetMaxWidth();
    return 0;
}

您可以在此处查看示例

对于具有几乎相同的不同类型,如果您想“克隆”一个类,或者在您的情况下,工厂模式可以完成这项工作,原型模式可以工作。


推荐阅读