Search code examples
c++strategy-pattern

Using strategy pattern to change method and its associate state


i like to create a class "track" that contains a state member and a kalman-filter method. I like to use different types of kalman filter. Since the interface for every kalman-filter is the same, i figured, i use the strategy pattern. The problem that i have, i also like to dynamically change the state member, when changing the strategy. Because the used state has to fit to the appropriat kalman filter.

Here a simplified Code snippet:

class CVState : public StateBase { ... };
class CAState : public StateBase { ... };

Kalman base:

class KalmanStrategy {
public:
  virtual void Prediction(StateBase* state) = 0;
  virtual void Correction(StateBase* state) = 0;
  virtual ~KalmanStrategy(){}

protected:
  KalmanStrategy() {}
};

Kalman Subclasses:

class KalmanCV : public KalmanStrategy {
public:
  KalmanCV(){}
  void Prediction(StateBase* state) {...}
  void Correction(StateBase* state) {...}
};
class KalmanCA : public KalmanStrategy {...}

Here my Track Class, it contains a state member, that has to be appropriate for Kalman.

class track {
public:
  track() {
    Kalman_ = new KalmanCV;
  }
  void ChangeStateModel(KalmanStrategy* K) {
     Kalman_ = K;
     //state_ = new CVState; // the state in track has to fit to the Kalman Class
                             // in this Case KalmanCV
  }
private:
  KalmanStrategy* Kalman_;
  StateBase* state_;
}

Is there a way, when changing the stratagy, to also change state_ ?


Solution

  • You could do this:

    struct KalmanModelCV {
      typedef KalmanCV filter_t;
      typedef StateCV state_t;
    };
    
    class track {
    public:
      track() {
        filter_ = NULL;
        state_ = NULL;
      }
      typedef<typename Model>
      void ChangeModel() {
         delete filter_;
         delete state_;
         filter_ = new typename Model::filter_t();
         state_ = new typename Model::state_t();
      }
    private:
      KalmanStrategy* filter_;
      StateBase* state_;
    };
    
    track t;
    t.ChangeModel<KalmanModelCV>();
    

    However, if every filter requires its own specific state type, it would be better to move the creation of states to the filter class. For example:

    class KalmanStrategy {
    public:
      virtual void Prediction(StateBase* state) = 0;
      virtual void Correction(StateBase* state) = 0;
      virtual StateBase* CreateState() = 0;
      virtual ~KalmanStrategy(){}
    
    protected:
      KalmanStrategy() {}
    };
    
    class KalmanCV : public KalmanStrategy {
    public:
      KalmanCV(){}
      void Prediction(StateBase* state) {...}
      void Correction(StateBase* state) {...}
      StateBase* CreateState() { return new StateCV(); } // KalmanCV only works with StateCV!
    };
    
    class track {
    public:
      track() {
        filter_ = NULL;
        state_ = NULL;
      }
      void ChangeModel(KalmanStrategy* strat) {
         delete filter_;
         delete state_;
         filter_ = strat;
         state_ = strat->CreateState();
      }
    private:
      KalmanStrategy* filter_;
      StateBase* state_;
    };