【问题标题】:How to design the config class for creating objects from a family of classes?如何设计配置类以从一系列类中创建对象?
【发布时间】:2017-12-01 18:18:23
【问题描述】:

我正在设计一个创建一系列类并对其进行管理的库。我需要设计用于从类实例化实例的配置类。这个配置类只是配置信息。

设计配置类的最佳方式是什么?配置类是否应该包含创建家族中任何类的对象所需的信息超集?或者,是否应该存在反映实际类层次结构的类层次结构。

举个具体的例子。假设我有一个名为 animalManager 的库,它根据用户配置创建各种动物并进行管理:

class animal {  // Animal base class
public:
    animal(bool isHerbivore, bool isMammal, bool isNocturnal) :
        mIsHerbivore(isHerbivore), mIsMammal(isMammal), mIsNocturnal(isNocturnal) { }

    virtual ~animal() { }

    // methods that do stuffs..
private:
    bool mIsHerbivore;
    bool mIsMammal;
    bool mIsNocturnal;
};

class snake : public animal {   // Snake animal
public:
    snake(bool isHerbivore, bool isMammal, bool isNocturnal, bool haveHood) :
        animal(isHerbivore, isMammal, isNocturnal), mHaveHood(haveHood) { }

    virtual ~snake() {}
private:
    bool mHaveHood;
};

class fish : public animal {
public:
    fish(bool isHerbivore, bool isMammal, bool isNocturnal, int numFins) :
        animal(isHerbivore, isMammal, isNocturnal), mNumFins(numFins) {
    }

    virtual ~fish() {}
private:
    int mNumFins;
};
// Cat, parrot, elephant, so on

class animalConfig { // User settings to create animals
    // What is the best way to design this class (/hierarchy) ?
};

class animalManager
{
public:
    animalManager() {}
    ~animalManager() {}

    animal* createAnimal(animalConfig *settings) {
        // Create and return animal
    }
    // So on
};

在上面的示例中,snakefish 需要在 animal 配置之上进行额外配置。如何表示这些配置?

【问题讨论】:

  • 我完全被你的动物等级搞糊涂了。为什么只有蛇有毒或无毒?所有其他动物都被认为是无毒的吗?
  • @tobi303 更新为准确
  • 为了OO,我倾向于对OO有点过敏,为什么要多态对待蛇和大象?为什么您需要针对不同动物的一种配置?顺便说一句,我不确定我是否能帮助你,只是想通过提出愚蠢的问题来理解和做出贡献:P
  • @tobi303 假设我经营一家动物园。我需要使用多态动物::吃来喂养所有的动物。并且,以多态方式执行诸如 animal::clean、animal::tranquilize 等操作。同时,我需要对非多态的动物进行操作,比如fish::swim、parrot::fly
  • 好的,那你为什么要让一个通用的createAnimal 采用通用配置而不是createFish(fishConfig)createSnake(snakeConfig) 呢?

标签: c++ design-patterns config object-oriented-analysis


【解决方案1】:

我建议使用工厂函数在配置解析和生成真正的动物类时使用的 meta_class 实例和一个类似于流的animalConfig。每个真实类都有一个 meta_class 对象。

class base_animals;
struct meta_base
{
  static std::vector< meta_base* > meta_base_list;
  meta_base(...):fn_(...), recognition_data_(...) { meta_base_list.push_back( this ); }
  std::unique_ptr< base_animals > fn_( animalConfig * );
  std::string recognition_data_;
};
class rabbit: public base_animal
{
   static meta_base mb;
   static std::unique_ptr< base_animals > make_bunny( animalConfig * );
   ...
};

// In source file
meta_base rabbit::mb( &rabbit::make_bunny, "rabbit" );

然后你就有了这些元对象的列表,animal* createAnimal(animalConfig *settings) 可以使用这些元对象来实例化任意动物类型。

for( auto meta* : meta_base::meta_base_list )
{
  if( settings->section_label() == meta->recognition_data_ )
  {
    return *(meta->fn_)( settings );
  }
  // Handle case where no meta class found
}

为此的输入数据可以是包含如下文本的流:

section rabbit
length X
weight Y
end

animalConfig 搜索文本“section”并获取标签“rabbit”(它存储并从section_label() 返回),然后 rabbit::make_bunny 方法负责解析特定于兔子的值。我认为尝试创建一个包含所有特定数据超集的 animalConfig 类并不容易。

【讨论】:

    猜你喜欢
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多