2012-11-05 99 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用於基類,則可以選擇取消信封類。