基于参数创建基类中的派生类



我的问题或多或少与需要的设计模式相同,以删除对象创建中的枚举和切换语句,但是我认为抽象的出厂模式在这里不适合使用。

我目前正在计划某些现有的DAL/ORM混合物库的重构/重新实现。在现有代码中的某个地方有看起来像这样的代码:

class Base
{
  static Base * create(struct Databasevalues dbValues)
  {
    switch(dbValues.ObjectType)
    {
    case typeA:
      return new DerivedA(dbValues);
      break;
    case typeB:
      return new DerivedB(dbValues);
      break;
    }
  }
}
class DerivedA : public Base
{
  // ...
}
class DerivedB : public Base
{
  // ...
}

因此,负责数据库通信的库将一个结构填充,其中包含有关数据库实体的所有信息,然后调用上面的创建()方法来实际创建ORM中的对应对象。但是我不喜欢一个小型班级了解其所有派生类的想法,也不喜欢Switch语句。我还想避免仅出于创建这些对象而创建另一个类。您如何看待当前的方法?您将如何实现此功能?

在这里已经讨论了数百万次。如果您不想创建单独的工厂课程,可以做到这一点。

class Base
{
public:
    template <class T>
    static void Register  (TObjectType type)
    {
       _creators[type] = &creator<T>;
    }
    static Base* Create (TObjectType type)
    {
        std::map <TObjectType, Creator>::iterator C = _creators.find (type);
        if (C != _creators.end())
          return C->second ();
        return 0;        
    }
private:
    template <class T>
    static Base* creator ()
    {
        return new T;
    }
private:
    typedef Base* (::*Creator) ();
    static std::map <TObjectType, Creator> _creators;
};
int main ()
{
   Base::Register <Derived1> (typeA);
   Base::Register <Derived2> (typeB);
   Base* a = Base::Create (typeA);
   Base* b = Base::Create (typeB);
}

,假设您将开关替换为映射,例如 map<ObjectType, function<Base* (DatabaseValues&)>>

现在,工厂(可能不在基类中),不需要了解所有子类。

但是,必须以某种方式填充地图。这意味着要么填充它(因此您的了解所有子类问题问题刚刚从一个地方推到另一个地方),要么您需要子类使用静态初始化来在地图中注册其出厂功能。/p>

无论您做什么,都需要开关案例或其他将隐藏相似逻辑的构造。

您可以和应该做的是从基础上删除创建方法 - 您完全正确,它不应该意识到它的派生方法。此逻辑属于另一个实体,例如工厂或控制器。

只是不使用枚举。它们不是OO的构造,这就是为什么Java一开始就没有它们(不幸的是,压力太大而无法添加它们)。

考虑而不是这样的枚举:

enum Types {
  typeA,
  typeB
};

这种不需要开关的结构(我认为另一个非OO构造)和地图:

types.h

class Base;
class BaseFactory {
public:
   virtual Base* create() = 0;
};     
class Types {
public:
  // possible values 
  static Types typeA;
  static Types typeB;
  // just for comparison - if you do not need - do not write...
  friend bool operator == (const Types & l, const Types & r) 
  { return l.unique_id == r.unique_id; }
  // and make any other properties in this enum equivalent - don't add them somewhere else 
  Base* create() { return baseFactory->create(); }
private:
   Types(BaseFactory* baseFactory, unsigned unique_id);
   BaseFactory* baseFactory;
   unsigned unique_id; // don't ever write public getter for this member variable!!!
};   

types.cpp

#include "Types.h"
#include "Base.h"
#include "TypeA.h"
#include "TypeB.h"
namespace {
  TypeAFactory typeAFactory;
  TypeBFactory typeAFactory;
   unsigned unique_id = 0;
}
Types Types::typeA(&typeAFactory, unique_id++);
Types Types::typeA(&typeBFactory, unique_id++);

所以您的示例(如果您真的需要此功能):

class Base
{
  static Base * create(struct Databasevalues dbValues)
  {
    return dbValues.ObjectType.create();
  }
};

缺少零件应该易于实现。

相关内容

  • 没有找到相关文章

最新更新