Ich entwickle einige komplexe Berechnungen, die die 'Schritte' erfordern (Strategie Muster Typ Implementierung) und ich bin mir nicht sicher, der beste Weg, die Schritt Unterberechnungsklassen in den Hauptteil injizieren Klasse.C++ injizieren 'Strategien' durch Konstruktor
Ich habe in richtlinienbasierten Design untersucht, aber lesen Sie das Policy Design ist für 'Kompilierzeit Polymorphismus' nicht Laufzeit. Außerdem war ich mir nicht sicher, wie man Vorlagen verwendet, da einige der Unterberechnungsklassen Konstruktorparameter benötigen.
Ich habe angefangen, virtuelle 'Interface'-Klassen für jeden Schritt zu implementieren und jeden Schritt als unique_ptr in den Konstruktor einzufügen, war mir aber nicht sicher, ob dies der richtige' moderne C++ 'Weg ist.
Ich fing anfänglich an, alle Funktionalität in der Hauptklasse zu implementieren, fand aber, dass es schwierig, wenn nicht unmöglich machte, jeden Schritt einzeln zu testen.
Die Struktur ist ähnlich wie unter:
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;
};
Jede Hilfe auf das beste Design zu bestimmen wäre toll, sehr geschätzt.
Mein Gedanke ist, dass der Versuch, die Top-Level-Klasse zu erstellen, die eine hartcodierte Reihe von Aktionen in eine Klasse komponiert ist zu restriktiv. Ich habe das Gefühl, dass ich versuche, eine Art flüssiges Interface zu verwenden, wo die Funktionen ihre Aktionen ausführen und das Ergebnis zurückgeben, so dass die nächste möglicherweise eine bessere Option ist. Ich habe nicht wirklich genug darüber nachgedacht, um ein konkretes Beispiel zu formulieren, das ist auch schwierig, da dein Beispiel so abstrakt ist. Sie können ein Beispiel aus C# Linq oder Java-Streams nehmen. –
@PaulRooney Interessanter Vorschlag. Ich bin mit Linq vertraut, da ich hauptsächlich C# bei der Arbeit verwende. Ich werde versuchen, etwas in diese Richtung zu bringen. – RobertW