экземпляр, заменяющий себя на новый экземпляр - PullRequest
2 голосов
/ 11 августа 2010

У меня есть некоторые действия ... Просмотр, Редактирование, Оформление заказа и т. Д. Бизнес-логика диктует, что если документ уже извлечен, все представления превращаются в изменения.как-то так:

class Action
{
public:
  Document document;
  virtual void execute();
};
class View, Edit, Checkout : public Action;

View::execute()
{
  if (document.isCheckedOut)
  {
    delete this;
    this = new Edit;
    this->execute();
  }
  /* execute view */
}

обновление: что вы, ребята, думаете об этом:

class Action
{
public:
  static int type;
  Document document;
  virtual void execute();
  static Action* construct(int type, Document document) = 0;
private:
  Action();
};
class View, Edit: public Action;

Action* View::construct(Document document)
{
  if (document.isCheckedOut)
    return new Edit(document);
  return new View(document);
}

Action* Edit::construct(Document document)
{
  return new Edit(document);
}

void onViewButton(Document document)
{
  Action *action = View::construct(document);
  action->execute();
  delete action;
}

Ответы [ 2 ]

1 голос
/ 11 августа 2010

Нет способа переназначить указатель this таким образом. Вы можете использовать реализацию интеллектуального указателя, чтобы сделать нечто подобное, добавив слой косвенности.

class action_ptr  
{
  Action* m_Data;
public:
  action_ptr(Action* value)
  {
     m_Data = value;
  }

  Action* operator->()
  {
      if(m_Data->isView() && m_Data->isCheckedOut())
      {
        delete m_Data;
        m_Data = new Edit();
      }
      return m_Data;
  }
};


 // usage
action_ptr pAction(new View());
pAction->DoViewStuff();
pAction->Checkout();
pAction->OtherStuff();  // If isCheckedOut returned true, this now magically operates on an Edit instead!

Это ни в коем случае не полная реализация, просто пример - утечки памяти и множество отсутствующих функций.

0 голосов
/ 11 августа 2010

Я бы, вероятно, решил это с помощью шаблона стратегии, где стратегии имеют функцию члена преобразования. Что-то вроде этого (неинтересные части кода опущены):

struct action_strategy {
  virtual ~action_strategy();

  virtual action_strategy *convert_strategy(document const &doc);
  virtual void execute() = 0;
};

class action { // Hur, hur :D
public:
  // construct with heap-allocated strategy
  action(action_strategy *strategy);

  void execute() {
    strategy_.reset(strategy_->convert_strategy(doc_);
    strategy_->execute();
  }

private:
  document doc_;
  std::auto_ptr<action_strategy> strategy_;
};

// Default: do nothing
action_strategy *action_strategy::convert_strategy(document const &doc) {
  return this;
}

class view : public action_strategy {
  // overload as necessary
  virtual action_strategy *convert_strategy(document const &doc);
};

action_strategy *view::convert_strategy(document const &doc) {
  if(doc.is_checked_out()) {
    return new edit();
  }

  return this;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...