基于策略的设计决策

时间:2009-08-23 13:11:39

标签: c++ templates policy-based-design

我有一个名为设备的课程,我可以看到两个政策: StatePolicy BehaviorPolicy
StatePolicy 保存并管理设备的状态 BehaviorPolicy 包装用C或C ++编写的设备驱动程序 现在我有两个问题:

  1. 如何在州和行为政策之间进行协调?
  2. 如何将所有设备存储在一个容器中?由于Device< X,Y>的类型不同,因此Device< N,M>我不能用一个容器存放它们。
  3. 编辑1: 这里有一些代码来说明我的问题:

    class AbstractDevice
    {
    public:
      virtual ~AbstractDevice() {}
    
      virtual void performAction() = 0;
      virtual const string &getName() const = 0;
      //virtual void changeState(const ??? &_state) = 0;  If I put a template here it won't solve my problem
    };
    
    template<typename T>
    class State
    {
    private:
      T state;
    protected:
      typedef T StateType;
    public:
      State() : state(1) {}
    
      const T &getState() { return state; }
      void setState(const T _state) { state = _state; }
    };
    
    template <class StatePolicy>
    class LightbulbBehvior : protected StatePolicy
    {
    private:
      typedef StatePolicy SP;
    public:
      virtual void performAction()
      {
        if ( SP::getState() )
          cout << "do stuff";
      }
    
      void changeState(const typename SP::StateType &_state)
      {
        setState(_state);
        performAction();
      }
    };
    
    template<class StatePolicy, template <class> class BehviorPolicy>
    class Device : public AbstractDevice, public BehviorPolicy<StatePolicy>
    {
    private:
      string sName;
    public:
      const string &getName() const { return sName; }
    };
    
    int main()
    {
      AbstractDevice *d = new Device<State<int>, LightbulbBehvior>();
      d->changeState(5);
      return 0;
    }
    

    编辑2: 这使代码工作有一个缺点,我必须维护所有允许的状态类型的列表。它看起来有点像我的访客模式。 有什么想法吗?

    class AbstractDevice
    {
    public:
      virtual ~AbstractDevice() {}
    
      virtual void performAction() = 0;
      virtual const string &getName() const = 0;
      virtual void changeState(const int &_state) = 0;
    };
    

    提前致谢,
    奥马尔。

3 个答案:

答案 0 :(得分:2)

这是完整的设计,并且它的工作非常好:

class AbstractState
{
public:
  virtual ~AbstractState() {}
};

class AbstractDevice
{
public:
  virtual ~AbstractDevice() {}

  virtual void performAction() = 0;
  virtual const string &getName() const = 0;
  virtual void changeState(const AbstractState &_state) = 0;
};

template<typename T>
class State : public AbstractState
{
private:
  T state;
protected:
  typedef T StateType;
public:
  State() {}
  State(const T _state) : state(_state) {}

  const T &getState() const { return state; }
  void setState(const T _state) { state = _state; }
};

template <class StatePolicy>
class LightbulbBehvior : protected StatePolicy
{
private:
  typedef StatePolicy SP;
public:
  virtual void performAction()
  {
    if ( SP::getState() )
      cout << "do stuff";
  }

  void changeState(const typename SP::StateType &_state)
  {
    setState(_state);
    performAction();
  }
};

template<class StatePolicy, template <class> class BehviorPolicy>
class Device : public AbstractDevice, public BehviorPolicy<StatePolicy>
{
private:
  string sName;

  typedef BehviorPolicy<StatePolicy> BP;
  typedef StatePolicy SP;
public:
  const string &getName() const { return sName; }

  void performAction()
  {
    BP::performAction();
  }

  void changeState(const AbstractState &_state)
  {
    BP::changeState(((const SP &)_state).getState());
  }
};

int main()
{
  AbstractDevice *d = new Device<State<int>, LightbulbBehvior>();
  d->changeState(State<int>(5));
  delete d;
  return 0;
}

@cjhuitt:一般来说我认为你是对的但是看一看并告诉我你的想法。

答案 1 :(得分:1)

我不确定你在第一个问题中的意思。关于第二个,您可以为 Device 类模板创建 DeviceBase 类。然后,您可以在容器中存储指向此基类的指针。


class DeviceBase
{
  //...
};

template <class T1, class T2>
class Device : public DeviceBase
{
  //...
};

答案 2 :(得分:1)

至于第一个问题:

  

如何在州和行为政策之间进行协调?

如果您需要在两个策略之间进行协调,则它们不是正交的。如果它们不是正交的,它们也不会适合您正在进行的设计类型。但是,看一下示例代码,我发现你已经有了依赖于状态的行为,所以我不知道这个问题的重点是什么......

至于第二个问题,ltcmelo有正确的答案,它也嵌入在您的代码中。如果您正在寻找一种方法来将模板化类保存在通用容器中,那么这是您最好的方法。为了克服changeState问题,您需要制作一些通用函数来更改状态,如openclose等。你不能做这些功能,也许你的代码通用。