2016-11-11 1 views
0

'steps'을 결정해야하는 복잡한 계산을 개발 중입니다 (전략 패턴 유형 구현). 단계 하위 계산 클래스를 메인에 주입하는 최선의 방법이 확실하지 않습니다. 수업.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 흥미로운 제안입니다. 직장에서 C#을 주로 사용하기 때문에 Linq에 익숙합니다. 나는 그 선을 따라 뭔가를 함께 가도록 할 것이다. – RobertW

답변

0

간단한 상속은 어떨까요? 귀하의 계산 클래스는 다음 (네가이 건설에 설정되는)에 대한 참조를 사용하든

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

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

, (스마트) 포인터의 std::reference_wrapper (null의 경우, 나중에 변경 될 수 없습니다) 또는 어떤 종류 (수 있습니다 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

관련 문제