如何设计用于从一族类创建对象的配置类?

时间:2017-12-01 18:18:24

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

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

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

一个具体的例子。假设我有一个名为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 config之上添加其他配置。如何表示这些配置?

1 个答案:

答案 0 :(得分: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类更容易。