Definição e estrutura
O modo Memento também é chamado de modo de token. O GOF define o modo de memorando como: sem destruir o encapsulamento, capture o estado interno de um objeto e salve esse estado fora do objeto. Dessa forma, o objeto pode ser restaurado ao seu estado salvo original posteriormente.
Ao falar sobre o modo de comando, mencionamos uma vez que o uso da função de comando intermediário pode realizar as funções de desfazer e refazer. A partir da definição, podemos ver que o modo de memorando é usado especificamente para armazenar o estado histórico do objeto, o que é de grande ajuda para implementar bem a desfazer e refazer as funções. Portanto, no modo de comando, as funções de desfazer e refazer podem ser implementadas em conjunto com o modo memorando.
De fato, ainda é muito simples perceber a função de salvar o estado de um objeto em um determinado momento - colocar os atributos a serem salvos no objeto em um objeto especializado no gerenciamento de backup e chamar o método acordado para colocar os atributos de backup de volta ao objeto original quando necessário. Mas você precisa dar uma boa olhada para permitir que seu objeto de backup acesse as propriedades no objeto original, isso significa que você deve divulgar todas as propriedades dos privados originais do objeto no pacote? Se sua abordagem quebrou o encapsulamento, considere refatorar.
O modo de memorando é apenas uma solução geral proposta pelo GOF para a questão de "recuperar o estado original de um objeto em um determinado momento". Portanto, em termos de como manter o encapsulamento - devido a fatores como características da linguagem, o padrão de memorando não é descrito em detalhes, mas explica apenas as idéias baseadas em C ++.
1) Função de lembrança: A função de memorando armazena o status interno da "função do iniciador do memorando". O "papel do iniciador do memorando" determina quais estados internos do "papel do iniciador de memorando" são armazenados conforme necessário. Para evitar outros objetos que não sejam o "papel do iniciador do memorando" de acessar os memorandos. Na verdade, os memorandos têm duas interfaces. A "função de gerente de memorando" pode ver apenas a interface estreita fornecida pelo memorando - é invisível para os atributos armazenados na função de memorando. O "Memorando Initiator Four" pode ver uma ampla interface - você pode obter os atributos que você coloca na função de memorando.
2) Função de iniciação de memorando (Originador): A "função de iniciação de memorando" cria um memorando para registrar seu estado interno no momento atual. Use memorandos para restaurar o estado interno quando necessário.
3) Função do gerente de memorando (zelador): Responsável por salvar memorandos. O conteúdo do memorando não pode ser operado ou verificado.
O diagrama de classes do modo de memorando é realmente simples:
Implementação de código geral
classe Originator {private string state = ""; public String getState () {Return State; } public void setState (State String) {this.state = state; } public Memento CreateMemento () {return New Memento (this.State); } public void Restorememento (Memento Memento) {this.SetState (Memento.getState ()); }} classe Memento {private String state = ""; public Memento (Estado da String) {this.state = state; } public string getState () {retornar estado; } public void setState (State String) {this.state = state; }} Class Caretaker {private Memento Memento; public Memento getMemento () {return Memento; } public void setMemento (Memento Memento) {this.Memento = Memento; }} public class Client {public static void main (String [] args) {Originator Originator = new Originator (); Originator.SetState ("Status 1"); System.out.println ("Estado inicial:"+Originator.getState ()); Zelador zelador = novo zelador (); caretaker.setMemento (Originator.CreateMemento ()); Originator.SetState ("Status2"); System.out.println ("Status após alterar:"+Originator.getState ()); Originator.restorememento (caretaker.getMemento ()); System.out.println ("Status após recuperação:"+Originator.getState ()); }}O código demonstra um exemplo de backup único de estado único. A lógica é muito simples: a variável de estado na classe Originator precisa ser backup para que possa ser restaurada quando necessário; Na classe Memento, há também uma variável de estado usada para armazenar o estado temporário da variável de estado na classe Originator; e a classe do zelador é usada para gerenciar a classe de memorando, usada para escrever estados ou recuperar estados no objeto de memorando.
Memorando multi-backup de vários estados
No exemplo da demonstração geral do código, a classe Originator possui apenas uma variável de estado que precisa ser backup, enquanto que geralmente, a função do iniciador é geralmente um javabeu, há mais de uma variável que precisa ser apoiada no objeto e mais de um estado que precisa ser backup. Este é um memorando multi-backup de vários estados. Existem muitas maneiras de implementar memorandos. Existem muitas deformações e métodos de processamento para memorandos. Métodos como o código geral geralmente não são usados. Na maioria dos casos, os memorandos são backups multi-estados e múltiplos. De fato, também é muito simples implementar multi-estados e multi-backup. O método mais comumente usado é adicionar um contêiner de mapa ao Memento para armazenar todos os estados e usar um contêiner de mapa na aula de zelador para armazenar todos os backups. Abaixo, damos um exemplo de vários estados e multif-backup:
classe Originator {private String state1 = ""; String privada state2 = ""; String privada state3 = ""; public String getState1 () {retornar estado1; } public void setState1 (String state1) {this.state1 = state1; } public string getState2 () {return state2; } public void setState2 (String state2) {this.state2 = state2; } public string getState3 () {return state3; } public void setState3 (String state3) {this.state3 = state3; } public Memento CreateMemento () {Return New Memento (beanutils.backupprop (this)); } public void Restorememento (Memento Memento) {beanutils.restoreProp (this, Memento.getStatemap ()); } public string tostring () {return "state1 ="+state1+"state2 ="+state2+"state3 ="+state3; }} classe Memento {mapa privado <string, object> statemap; public Memento (map <string, objeto> map) {this.statemap = map; } mapa público <string, objeto> getStatemap () {return statemap; } public void setStatemap (map <string, object> statemap) {this.statemap = statemap; }} classe beanutils {public static map <string, object> backupprop (objeto bean) {map <string, object> resultado = new hashmap <string, object> (); tente {beaninfo beaninfo = introspector.getbeaninfo (bean.getclass ()); PropertyDescriptor [] descritores = beaninfo.getPropertyDescriptores (); for (PropertyDescriptor des: descritores) {String fieldName = des.getName (); Método getter = des.getReadMethod (); Objeto fieldValue = getter.invoke (feijão, novo objeto [] {}); if (! fieldName.equalsignorecase ("classe")) {result.put (fieldname, fieldValue); }}}} catch (Exceção e) {e.printStackTrace (); } resultado de retorno; } public static void RestoreProp (objeto Bean, mapa <string, object> propMap) {try {beaninfo beaninfo = introspector.getbeaninfo (bean.getclass ()); PropertyDescriptor [] descritores = beaninfo.getPropertyDescriptores (); for (PropertyDescriptor des: descritores) {String fieldName = des.getName (); if (propmap.containsKey (fieldname)) {método setter = des.getWriteMethod (); setter.invoke (bean, novo objeto [] {propmap.get (fieldname)}); }}} catch (Exceção e) {e.printStackTrace (); }}} classe Caretaker {private mapa <string, lembrança> memmap = new hashmap <string, lembrança> (); public Memento GetMemento (String Index) {return memmap.get (index); } public void SetMemento (String Index, Memento Memento) {this.memmap.put (índice, lembrança); }} classe client {public static void main (string [] args) {Originator ori = new Originator (); Zelador zelador = novo zelador (); ori.setState1 ("China"); ori.setState2 ("forte"); ori.setState3 ("prosperidade"); System.out.println ("=== status de inicialização ===/n"+ori); caretaker.setMemento ("001", ori.createMemento ()); ori.setState1 ("software"); ori.setState2 ("estrutura"); ori.setState3 ("Excelente"); System.out.println ("=== status modificado ===/n"+ori); ori.restorememento (caretaker.getMemento ("001")); System.out.println ("=== status restaurado ===/n"+ori); }} As vantagens e desvantagens do modo de memorando e as vantagens do modo de memorando para cenários aplicáveis são:
Quando o status da função do iniciador muda, pode ser uma mudança errada. Podemos restaurar essa alteração errada usando o modo memorando.
O status do backup é salvo fora da função do iniciador; portanto, a função do iniciador não precisa gerenciar o status de cada backup.
Desvantagens do modo de memorando:
Em aplicações reais, o modo de memorando é multi-estadual e multi-backup. O estado do papel do iniciador precisa ser armazenado no objeto de memorando, que consome recursos relativamente severamente.
Se você precisar fornecer operações de reversão, o uso do modo de memorando é muito adequado, como operações de transação JDBC, recuperação Ctrl+Z dos editores de texto, etc.