2

Context

I'm attempting to design a modelling framework that is modular and easy to extend and test. (I'm trying to follow open/closed, dependency injection, and composition over inheritence principles).

I have a hierachy of model objects, which contain methods, some common to all and others specific to certain models. I also have a hierachy of estimation methods which work on various subsets of the models.

Each estimator class requires a model object, which is passed using the constructor.

While constructing the objects at compile is no problem, I'm struggling to come up with a way to do so in run-time without resorting to dynamic_casting of parent model interface in the estimator. While it works, it's potentially unsafe if an invalid combination of model and estimator are put together. I've also read that dynamic_casting is usually a sign of poor code design.

Question

Are there any standard design patterns or techniques to avoid using dynamic_cast when object composition details are only known at run-time?

Or does this suggest the object hierachy needs to be completely reworked to avoid this kind of conditional dependency between objects?

Code Example

#include <iostream>
#include <unordered_map>
class i_model {
public:
 virtual double getparameter_a() = 0;
 };
class i_model_A : public i_model {
public:
 virtual double getparameter_b() = 0;
};
class model_A : public i_model_A {
public:
 double getparameter_a() { return 4.0; };
 double getparameter_b() { return 4.0; };
};
class i_model_B : public i_model {
public:
 virtual double getparameter_c() = 0;
};
class model_B : public i_model_B {
public:
 double getparameter_a() { return 5.0; };
 double getparameter_c() { return 2.0; };
};
class i_estimator {
public:
 virtual double getestimate() = 0;
};
class estimator_1 : public i_estimator {
public:
 estimator_1(i_model* in) : model(dynamic_cast<i_model_A*>(in)) {};
 double getestimate() { return model->getparameter_a() + model->getparameter_b(); };
private:
 i_model_A* model;
};
class estimator_2 : public i_estimator {
public:
 estimator_2(i_model* in) : model(dynamic_cast<i_model_B*>(in)) {};
 double getestimate() { return model->getparameter_a() + model->getparameter_c(); };
private:
 i_model_B* model;
};
int main()
{
 int a;
 int b;
 i_model* model = nullptr;
 i_estimator* estimator = nullptr;
 std::cout << "Select model: ";
 std::cin >> a;
 std::cout << "\nSelect estimator: ";
 std::cin >> b;
 
 switch(a) {
 case 1: model = new model_A(); break;
 case 2: model = new model_B(); break;
 }
 switch (b) {
 case 1: estimator = new estimator_1(model); break;
 case 2: estimator = new estimator_2(model); break;
 }
 std::cout << "\nEstimator value = " << estimator->getestimate();
} 
asked Jul 16, 2021 at 1:02
1

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.