Шаблон команды: где создавать элементы команды?

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

Следующие примеры иллюстрируют эту проблему: A Document имеет функцию setText() который устанавливает текст:

class Document {
public:
void setText(const std::string text) {
if (commandManager()->isActive()) {
// called by SetTextCommand
m_text = text;
} else {
// called somewhere in the application
commandManager()->addAndExecute(new SetTextCommand(this, text));
}
}
std::string text() const { return m_text; }

CommandManager * commandManager() const { return m_commandManager; }
private:
std::string m_text;
CommandManager * m_commandManager;
}

Здесь SetTextCommand выполнит document->setText(text) как это:

class SetTextCommand : public Command {
public:
SetTextCommand(Document * doc, const std::string & text)
: Command(), m_doc(doc), m_oldText(doc->text()), m_text(text)
{}
void redo() override {
m_doc->setText(m_text);
}
void undo() override {
m_doc->setText(m_oldText, false);
}
}

SetTextCommand обрабатывается CommandManager как это:

CommandManager::addAndExecute(Command * command) {
m_doc->commandManager()->setActive(true); // THIS IS THE TRICK
command->redo();
m_doc->commandManager()->setActive(false);  // THIS IS THE TRICK
m_stack->push_back(command);
}

Хитрость в том, что при запуске redo(), CommandManager::isActive() установлен в правда. Следовательно, Document::setText() установит m_text,

Очевидно, что все функции установки документа должны следовать if (commandManager()->isActive()) { ... } else { ... } парадигма. Это потому, что сами Команды создаются в функциях сеттера.

Вопрос сейчас: Это хороший способ реализовать шаблон команды? Или есть более чистые решения для создания команд, в то же время имея хороший API?

Пожалуйста, будьте многословны со своими ответами.

0

Решение

Я думаю, что было бы довольно уродливо, чтобы повторить if (commandManager()->isActive()) везде … наверное, приятнее иметь setText всегда делай SetTextCommand путь, и создайте новый setTextImmediate метод, который SetTextCommand можешь использовать.

1

Другие решения


По вопросам рекламы [email protected]