Stuck on how to apply OOP to estimation problems
<p>I have been reading online articles and in the process of reading "Head First Design Patterns", and it seems one of the fundamental OOP is "encapsulate what varies". I am stuck on how to apply that to my problem, might not even be looking at the problem the right way so I was hoping to get some advice.</p>

<p>I will sum up my application, desired goal, and problem I am facing than at the end show the code I have. I omitted some parts of the code and simplified the inputs. I figured since this is more of a design problem, I dont need to show all the constructors and so on.</p>

<p>My application takes a bunch of measurements and processes the measurements through what I will call estimators: Least Squares (LS), extended Kalman filter (EKF) or sequential least squares (SLS). I would like to at run-time change which estimator is used.</p>

<p>Each estimator fundamentally has two methods "Update()" and "DetectBlunders()" (and called in that order) with the internals of each method being different dependent on the estimator, but the objective is the same. So I originally have a "BaseEstimator" that has methods "Update()" and "DetectBlunders()" and each estimator inherits from "BaseEstimator". Through implementing the concrete estimators I started to realize some problems. </p>

<p>1) EXF requires one extra step "Predict()" before "Update()". So I originally added a "Predict()" method to "BaseEstimator" and in LS and SLS "Predict()" does nothing. However this kind of seems wrong some how. If I changed "Predict()" or removed it from "BaseEstimator" in my LS and SLS would be affected even though they shouldnt have a "Predict()" in the first place.</p>

<p>2) EKF and SLS require one extra input to "Update()". So I did something similar as before, I added this extra input in "Update()" in the "BaseEstimator" and in the override in LS I just pass an empty variable. Again, this seems wrong. This input is another object so I actually pass just an empty constructor in LS, and in LS I test if the constructor is empty, seems very wrong.</p>

<p>Would anyone have any advice on what I can do, if anything. Maybe this is the only way to approach the problem. The end goal was to make a "EstimatorFactory" (the only design principle I understand enough to use) that at run time would make an Estimator. I also may add other estimators in the future like "Particle Filter (PF)". Again I am very new to actually using OOP, old me would have just used if/switches everywhere and have one class that does all three estimators (a couple thousand lines later).</p>

<pre><code>class BaseEstimator {
public:
    // I dont actually call my inputs 1,2,3,4
    virtual bool Update(
        double input1, // Required by all three estimators
        double input2, // Required by all three estimators
        double input3,  // Required by all three estimators
        double input4 // Not required in LS, but required in EXF and SLS 
    ); 

    virtual bool DetectBlunders() const = 0;

    // Only required by EXF
    virtual bool Predict(
        double input1,
        double input2
    ) = 0;
};

class EXF : public BaseEstimator {
    public:
        bool Update(
            double input1,
            double input2,
            double input3,
            double input4);

    bool DetectBlunders() const;

    bool Predict(
        double input1,
        double input2);
};

class LS : public BaseEstimator {
public:
    bool Update(
        double input1,
        double input2,
        double input3,
        double input4 = 0 // This is not needed in LS so I actually pass it an empty constructor
    );

    bool DetectBlunders() const;

    bool Predict(
        double input1,
        double input2) {
        // Do nothing since its not required in LS
    }
};

class SLS : public BaseEstimator {
public:
    bool Update(
        double input1,
        double input2,
        double input3,
        double input4);

    bool DetectBlunders() const;

    bool Predict(
        double input1,
        double input2) {
        // Do nothing since its not required in SLS
    }
}; 
</code></pre>