Pular para o conteúdo

Boas práticas e padrões · Padrões comportamentais · 4 min de leitura

Command (desfazer, filas e ações)

Transforma uma ação em objeto: dá para enfileirar, registrar, refazer e desfazer.

Botão / atalho → Editor1Editor → Negrito: executarexecutar2Negrito → Documento3Editor → Histórico: empilhaempilha4Botão / atalhoBotão / atalhoEditor — invocadorEditorinvocadorNegrito — executar / desfazerNegritoexecutar / desfazerDocumento — receptorDocumentoreceptorHistórico — pilhaHistóricopilha

Arraste para o lado para ver o diagrama inteiro.

Cada ação vira um objeto com executar() e desfazer(); o histórico é só uma pilha desses objetos.

Usos

  • Desfazer/refazer em editores.
  • Filas de trabalho e sincronização offline: grave os comandos e envie quando houver rede.
  • Ações de UI no padrão MVI: sealed interface Acao descreve tudo o que a tela pode pedir.

Ligação com eventos

Comandos dizem "faça isto" (imperativo, podem falhar); eventos dizem "isto aconteceu" (fato). Separar os dois deixa logs e auditoria claros — a mesma ideia do CQRS.

No código

✓ ExemploKotlin
interface Comando { fun executar(); fun desfazer() }

class InserirTexto(private val doc: StringBuilder, private val pos: Int, private val texto: String) : Comando {
  override fun executar() { doc.insert(pos, texto) }
  override fun desfazer() { doc.delete(pos, pos + texto.length) }
}

class Editor(val doc: StringBuilder = StringBuilder()) {
  private val feitos = ArrayDeque<Comando>()
  private val desfeitos = ArrayDeque<Comando>()
  fun executar(c: Comando) { c.executar(); feitos.addLast(c); desfeitos.clear() }
  fun desfazer() = feitos.removeLastOrNull()?.also { it.desfazer(); desfeitos.addLast(it) }
  fun refazer() = desfeitos.removeLastOrNull()?.also { it.executar(); feitos.addLast(it) }
}

Desfazer e refazer são duas pilhas. Qualquer ação nova só precisa implementar executar() e desfazer().

Em resumo

Referências

Continue aprendendo

Todos os temas de boas práticas e padrões →