2016-11-11 6 views
0

「ステップ」を決定する必要がある(戦略パターンタイプの実装)複雑な計算をいくつか開発していますが、ステップのサブ計算クラスをメインに注入する最良の方法は不明ですクラス。コンストラクタを通してC++に注入する

私はポリシーベースの設計を検討しましたが、ポリシーデザインは実行時ではなく「コンパイル時のポリモーフィズム」に関するものです。さらに、サブ計算クラスのいくつかがコンストラクタパラメータを必要とするため、テンプレートの使用方法がわかりませんでした。

各ステップごとに仮想 'インターフェイス'クラスを実装し、各ステップをコンストラクタ内にunique_ptrとして注入しましたが、これが正しい '最新のC++'の方法であるかどうかはわかりませんでした。

私は最初、メインクラスのすべての機能の実装を開始しましたが、各ステップを個別にテストすることが不可能ではないにしても、これは困難でした。

構造は以下のようになります。

class CalculationStepA 
{ 
public: 
    // default constructor 

    StepAResult performStep(const input& requiredInput); 
}; 

class CalculationStepBType1 
{ 
public: 
    // default constructor 

    StepBResult performStepB(const stepBInput& requiredInput); 
}; 

class CalculationStepBType2 
{ 
public: 
    CalculationStepBType2(const inputIOnlyNeedForType2& parameters) 
    { 
    // initialize class members from input 
    // need for this calculation type 
    } 

    StepBResult performStepB(const stepBInput& requiredInput); 
}; 

class CalculationStepCType1 
{ 
public: 
    CalculationStepBType2(const inputIOnlyNeedForType1& parameters) 
    { 
    // initialize class members from input 
    // need for this calculation type 
    } 

    StepCResult performStepC(const stepCInput& requiredInput); 
}; 

class CalculationStepCType2 
{ 
public: 
    CalculationStepBType2(const inputIOnlyNeedForType2& parameters) 
    { 
    // initialize class members from input 
    // need for this calculation type 
    } 

    StepCResult performStepB(const stepCInput& requiredInput); 
}; 

class ClassThatUsesAllTheCalculations 
{ 
public: 
    ClassThatUsesAllTheCalculations(/* take required parameters that determine which step types I need */) 
    {} 

    // possible constructor? 
    ClassThatUsesAllTheCalculations(
     std::unique_ptr<IStepACalculationStrategy> stepA, 
     std::unique_ptr<IStepBCalculationStrategy> stepB,  
     std::unique_ptr<IStepCCalculationStrategy> stepC) 
    { 

    } 

    FinalResult executeCalculation(const finalInputRequiredHere& input) 
    { 
    auto stepAresult = stepACalculator(somethingFromInput); 
    // logic to use stepA and determine if we should continue 

    auto stepBresult = stepBCalculator(somethingFromStepAResult); 
    // again, logic to use stepB and determine if we should continue 

    auto stepCresult = stepCCalculator(somethingFromStepBResult); 
    // assemble final result 

    return theFinalResult 
    } 


    // other method needed to setup calculation 


private: 
    TypeForStepACalculation stepACalculator; 
    TypeForStepBCalculation stepBCalculator; 
    TypeForStepCCalculation stepCCalculator; 
}; 

最高のデザインを決定する上の任意のヘルプは高く評価素晴らしいことです。

+0

私の考えはクラスにアクションのハードコードされた数を構成するトップレベルのクラスを作成しようとするとあまりにも限定的であるということです。私は、関数が自分のアクションを実行して結果を返すように構成されたある種の流暢なインターフェースをしようとしていると感じ、次のものがそれを使う方が良い選択肢かもしれない。私は本当に具体的な例を定式化するのに十分な考えを与えられていないが、あなたの例が非常に抽象的であるため、これも難しい。あなたは、C#のLinqまたはJavaストリームからの例を取るかもしれません。 –

+0

@PaulRooney面白い提案。私はLinqに慣れています。私は主にC#を使用しています。私はそれらの行に沿って何かを一緒に置くことに行きます。 – RobertW

答えて

0

単純な継承についてはどうですか?あなたの計算クラスは、その後(HASTが建設に設定される)の参照を使用するかどうか

struct StepA{ 
    virtual StepAResult perform(StepAParams)=0; 
}; 

struct someStepAImpl : public StepA{ 
    virtual StepAResult perform(StepAParams params) override { 
     //actual implementation 
    } 
}; 

、(スマート)ポインタのstd::reference_wrapper(ヌルが、後で変更することはできません)、またはいくつかの種類(かもしれないnullptr、ドンそのことを確認するのは忘れないでください。ただし、ライフタイムを管理する場合は最も簡単です)は、その使用方法やオブジェクトのライフタイムの管理方法によって異なります。あなたが行ったようにunique_ptrを使用した例は次のようになります。

class Calculator 
{ 
public: 
    Calculator(
     std::unique_ptr<StepA> stepA, 
     std::unique_ptr<StepB> stepB,  
     std::unique_ptr<StepC> stepC 
    ) 
    :m_stepA(std::move(stepA)),m_stepB(std::move(stepB)),m_stepC(std::move(stepC)) 
    {} 

    FinalResult executeCalculation(const finalInputRequiredHere& input) 
    { 
     //logic 
     auto stepAresult = stepA->perform(StepAParams); 
     //logic 
     auto stepBresult = stepB->perform(StepBParams); 
     //logic 
     auto stepCresult = stepC->perform(StepAParams); 
     //logic 
     return FinalResult(); 
    } 

private: 
    std::unique_ptr<StepA> m_stepA=nullptr; 
    std::unique_ptr<StepB> m_stepB=nullptr; 
    std::unique_ptr<StepC> m_stepC=nullptr; 
}; 


void somewhereElse(){ 
    std::unique_ptr<StepA> stepa(new someStepAImpl()); 
    std::unique_ptr<StepB> stepa(new someStepBImpl()); 
    std::unique_ptr<StepC> stepa(new someStepCImpl()); 
    Calculator calc(
     std::move(stepa), 
     std::move(stepb), 
     std::move(stepc) 
    ); 
    calc.executeCalculation(...); 
} 
+0

これは完全に機能しています。これは私がもともと傾けていた解決策でした。私は、必要な歩数の計算を組み立てて注入するための工場を作りました。 – RobertW

関連する問題