2012-11-05 68 views
2

我想写一个线性程序解决库。因此使用了几种求解器,如cplex或gurobi。我已经有了每个接口(都包含相同的函数来包装它们来解决特定的代码)。正确的继承/类结构

现在我想要一个可以实例化的类'LinearProgram',例如通过LinearProgram(“cplex”),然后调用cplex求解器。

我的第一个想法是使用超类“求解器”,它是所有求解器接口的基类,其中包含作为虚拟声明的相应函数。但后来我得到了一个无法实例化的抽象类。 所以在LinearProgram中,我想要一个变量Solver,它根据构造函数中给出的字符串进行实例化。

我确定一个合适的解决方案是非常明显的,但我现在所能想到的一切都不令人满意。

感谢您的帮助。

+4

使用你的求解器超类的想法,仅实例化子类,并且不要使用超类的值(仅使用指针和引用)。 – Wug

回答

0

这说明你的描述:

class Solver { 
...abstract base 
}; 

class SolverFactory { 
public: 
    Solver* NewSolverWithName(const std::string& pSolverName); 
}; 

class LinearProgram { 
public: 
    LinearProgram(const std::string& pSolverName) : 
     d_solver(SolverFactory::NewSolverWithName(pSolverName)) { 
    } 
private: 
    some_auto_pointer<Solver> d_solver; 
}; 

class cplex_Solver : public Solver { 
... 
    static std::string Name(); 
}; 

Solver* SolverFactory::NewSolverWithName(const std::string& pSolverName) { 
    if (pSolverName == cplex_Solver::Name()) { 
     return new cplex_Solver(); 
    } 
    ... 
} 
+3

我不会把工厂类分开。我会在'Solver'类中有一个静态工厂方法。 – Omnifarious

+0

@实际上,对于一个给定的问题,更好的方法取决于很多事情。但在某些情况下为+1。如果写成产品代码,我会做很多不同的事情。 – justin

+0

感谢您的回复。这似乎是我的问题很好的解决方案。但是我有一个关于实现的最后一个小问题:我有'求解器'基类和'CplexSolver'等求解器类。我添加了一个静态函数\t'静态求解器* NewSolverWithName(常量的std :: string&pSolverName){ \t \t如果(pSolverName == CplexSolver ::名称()){ \t \t \t回报新CplexSolver(); \t \t} \t}' – user1801173

0

这是两种不同的设计模式相结合的工作。

第一个是Envelope Letter模式,第二个是Strategy Pattern

继续使用您当前拥有的基类,并创建一个派生类,该类只将该调用转发给指向基类的嵌入式指针。派生类现在可以通过价值自由传递。

基类还可以包含一个静态成员函数,该函数返回一个指向基类的指针。这个静态成员函数将允许您通过使用字符串名来查找它来实例化派生类。这提供了一种在运行时选择算法的简便方法。

但是知道他们想要哪个派生类(哪种策略)的人可以用'new'创建一个,并将其包含在信封类的实例中。

如果您决定仅将shared_ptr用于基类,则可以选择取消信封类。