dependency injection - C++ injecting 'strategies' through constructor -
i'm developing complex calculations require 'steps' determined (strategy pattern type implementation) , i'm not sure best way inject step subcalculation classes main class.
i've looked policy-based design read policy design 'compile time polymorphism' not runtime. plus, wasn't sure how use templates of subcalculation classes need constructor parameters.
i've started implementing virtual 'interface' classes each step , injecting each step unique_ptr in constructor wasn't sure if correct 'modern c++' way.
i started implementing functionality in main class found made difficult if not impossible unit test each step independently.
the structure similar below:
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 input // need calculation type } stepbresult performstepb(const stepbinput& requiredinput); }; class calculationstepctype1 { public: calculationstepbtype2(const inputionlyneedfortype1& parameters) { // initialize class members input // need calculation type } stepcresult performstepc(const stepcinput& requiredinput); }; class calculationstepctype2 { public: calculationstepbtype2(const inputionlyneedfortype2& parameters) { // initialize class members input // need calculation type } stepcresult performstepb(const stepcinput& requiredinput); }; class classthatusesallthecalculations { public: classthatusesallthecalculations(/* take required parameters determine step types 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 use stepa , determine if should continue auto stepbresult = stepbcalculator(somethingfromsteparesult); // again, logic use stepb , determine if should continue auto stepcresult = stepccalculator(somethingfromstepbresult); // assemble final result return thefinalresult } // other method needed setup calculation private: typeforstepacalculation stepacalculator; typeforstepbcalculation stepbcalculator; typeforstepccalculation stepccalculator; }; any on determining best design great appreciated.
whats simple inheritance?
struct stepa{ virtual steparesult perform(stepaparams)=0; }; struct somestepaimpl : public stepa{ virtual steparesult perform(stepaparams params) override { //actual implementation } }; whether calculation class uses reference (hast set on construction), std::reference_wrapper (not null, can changed later) or kind of (smart) pointer (might nullptr, don't forget check that, easiest when comes managing lifetime) depends on how plan use , how want manage lifetime of objects. example using unique_ptr did be:
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(...); }
Comments
Post a Comment