Na minha opinião, o UNDO / REDO poderia ser implementado de 2 maneiras amplamente. 1. Nível de comando (denominado nível de comando Desfazer / Refazer) 2. Nível de documento (denominado Desfazer / Refazer global)
Nível de comando: como muitas respostas apontam, isso é alcançado de forma eficiente usando o padrão Memento. Se o comando também suportar o registro da ação no diário, um refazer será facilmente suportado.
Limitação: Uma vez que o escopo do comando está fora, desfazer / refazer é impossível, o que leva ao nível de documento (global) desfazer / refazer
Acho que seu caso se encaixaria no desfazer / refazer global, pois é adequado para um modelo que envolve muito espaço de memória. Além disso, isso também é adequado para desfazer / refazer seletivamente. Existem dois tipos primitivos
- Desfazer / refazer toda a memória
- Nível de objeto Desfazer Refazer
Em "Desfazer / Refazer toda a memória", toda a memória é tratada como um dado conectado (como uma árvore, uma lista ou um gráfico) e a memória é gerenciada pelo aplicativo em vez do sistema operacional. Portanto, operadores new e delete se em C ++ estiverem sobrecarregados para conter estruturas mais específicas para implementar efetivamente operações como a. Se algum nó for modificado, b. mantendo e apagando dados, etc., A maneira como funciona é basicamente copiar toda a memória (assumindo que a alocação de memória já está otimizada e gerenciada pelo aplicativo usando algoritmos avançados) e armazená-la em uma pilha. Se a cópia da memória for solicitada, a estrutura da árvore é copiada com base na necessidade de uma cópia superficial ou profunda. Uma cópia profunda é feita apenas para a variável modificada. Uma vez que cada variável é alocada usando alocação personalizada, o aplicativo tem a palavra final quando excluí-lo, se necessário. As coisas se tornam muito interessantes se tivermos que particionar o Desfazer / Refazer quando acontecer que precisamos desfazer / Refazer de maneira programática e seletiva um conjunto de operações. Neste caso, apenas essas novas variáveis, ou variáveis excluídas ou variáveis modificadas recebem um sinalizador para que Desfazer / Refazer apenas desfaça / refaça aquelas coisas da memória se tornam ainda mais interessantes se precisarmos fazer um Desfazer / Refazer parcial dentro de um objeto. Quando for esse o caso, uma ideia mais recente de "Padrão de visitante" é usada. É chamado de "Desfazer / refazer no nível do objeto" ou variáveis excluídas ou modificadas recebem um sinalizador para que Desfazer / Refazer apenas desfaça / refaça as coisas da memória. As coisas se tornam ainda mais interessantes se precisarmos fazer um Desfazer / Refazer parcial dentro de um objeto. Quando for esse o caso, uma ideia mais recente de "Padrão de visitante" é usada. É chamado de "Desfazer / refazer no nível do objeto" ou variáveis excluídas ou modificadas recebem um sinalizador para que Desfazer / Refazer apenas desfaça / refaça as coisas da memória. As coisas se tornam ainda mais interessantes se precisarmos fazer um Desfazer / Refazer parcial dentro de um objeto. Quando for esse o caso, uma ideia mais recente de "Padrão de visitante" é usada. É chamado de "Desfazer / refazer no nível do objeto"
- Nível de objeto Desfazer / Refazer: Quando a notificação para desfazer / refazer é chamada, cada objeto implementa uma operação de streaming em que o streamer obtém do objeto os dados antigos / novos que estão programados. Os dados que não podem ser alterados são mantidos inalterados. Cada objeto recebe um streamer como argumento e dentro da chamada UNDo / Redo, ele faz o stream / unstreams dos dados do objeto.
Ambos 1 e 2 podem ter métodos como 1. BeforeUndo () 2. AfterUndo () 3. BeforeRedo () 4. AfterRedo (). Esses métodos devem ser publicados no comando Undo / redo básico (não no comando contextual) para que todos os objetos implementem esses métodos também para obter uma ação específica.
Uma boa estratégia é criar um híbrido de 1 e 2. A beleza é que esses métodos (1 e 2) usam padrões de comando