Политические проектные решения - PullRequest
3 голосов
/ 23 августа 2009

У меня есть класс с именем Устройство , которое принимает две политики, насколько я вижу: StatePolicy и BehaviorPolicy .
StatePolicy хранит и управляет состоянием устройства.
BehaviorPolicy включает драйвер устройства, написанный на C или C ++.
Теперь у меня есть два вопроса:

  1. Как координировать действия государства и политики поведения?
  2. Как мне хранить все устройства в одном контейнере? Поскольку тип устройства отличается от типа устройства , я не могу хранить их в одном контейнере.

РЕДАКТИРОВАТЬ 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 ]

2 голосов
/ 23 августа 2009

Вот полный дизайн, который работает и справляется со своей задачей:

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 голос
/ 23 августа 2009

По первому вопросу:

Как координировать действия государства и политики поведения?

Если вам необходимо согласовать две политики, они не являются ортогональными. Если они не ортогональны, они также не будут соответствовать типу дизайна, который вы делаете. Однако, глядя на пример кода, я вижу, что у вас уже есть поведение, основанное на состоянии, поэтому я не знаю, в чем смысл этого вопроса ...

Что касается второго вопроса, ltcmelo имеет правильный ответ, который также встроен в ваш код. Если вы ищете способ сохранить шаблонные классы в универсальном контейнере, это ваш лучший способ. Чтобы преодолеть проблему changeState, вам нужно будет сделать некоторые универсальные функции для изменения состояний, как вы хотите ... например, open, close и т. Д. Если вы не можете сделать это функции, возможно, ваш код слишком универсальный.

1 голос
/ 23 августа 2009

Я не уверен, что вы имеете в виду в первом вопросе. Что касается второго, вы можете создать DeviceBase класс для шаблона Device . Затем вы можете хранить указатели на этот базовый класс в контейнерах.


class DeviceBase
{
  //...
};

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