Definición y estructura
El modo Memento también se llama modo token. GOF define el modo memo como: sin destruir la encapsulación, captura el estado interno de un objeto y guarde este estado fuera del objeto. De esta manera, el objeto se puede restaurar a su estado guardado original más adelante.
Cuando hablamos del modo de comando, una vez mencionamos que usar el rol de comando intermedio puede realizar las funciones de deshacer y rehacer. Desde la definición, podemos ver que el modo MEMO se usa específicamente para almacenar el estado histórico del objeto, lo cual es de gran ayuda para implementar bien las funciones de deshacer y rehacer. Por lo tanto, en el modo de comando, las funciones de deshacer y rehacer se pueden implementar junto con el modo memo.
De hecho, todavía es muy simple simplemente darse cuenta de la función de guardar el estado de un objeto en un momento determinado: coloque los atributos para guardar en el objeto en un objeto que se especialice en la administración de copia de seguridad, y llame al método acordado para volver a colocar los atributos de copia de seguridad en el objeto original cuando sea necesario. Pero debe analizar bien para permitir que su objeto de respaldo acceda a las propiedades en el objeto original, ¿significa que debe revelar todas las propiedades de las privadas originales del objeto en el paquete? Si su enfoque ha roto la encapsulación, entonces debe considerar la refactorización.
El modo Memorandum es solo una solución general propuesta por GOF para el problema de "recuperar el estado original de un objeto en un momento determinado". Por lo tanto, en términos de cómo mantener la encapsulación, debido a factores como las características del lenguaje, el patrón de memorándum no se describe en detalle, sino que solo explica las ideas basadas en C ++.
1) Rol de recuerdo: El rol de memorándum almacena el estado interno del "Memorandum Iniciador del iniciador". El "rol de iniciador de memorándum" determina qué estados internos del "papel iniciador del memorando" se almacenan según sea necesario. Para evitar que otros objetos distintos del "Memorandum Iniciador del Iniciador" accedan a las notas. Las notas en realidad tienen dos interfaces. El "rol de administrador de memo" solo puede ver la interfaz estrecha proporcionada por la nota: es invisible para los atributos almacenados en el rol de memo. El "Memorandum Iniciator Role" puede ver una interfaz amplia: puede obtener los atributos que pone en el papel de memorándum.
2) Iniciación de memo (Originador): El "rol de iniciación de memo" crea una nota para registrar su estado interno en el momento actual. Use notas para restaurar el estado interno cuando sea necesario.
3) Memorandum Manager (Caretaker): Responsable de salvar memorandos. El contenido del memo no se puede operar o verificar.
El diagrama de clase del modo memo es realmente simple:
Implementación del código general
Class Originator {private String state = ""; public String getState () {return State; } public void setState (string state) {this.state = state; } public Memento Creememento () {return New Memento (this.state); } public void RestorementO (Memento Memento) {this.setState (Memento.getState ()); }} class Memento {private String state = ""; Public Memento (String State) {this.state = state; } public String getState () {State de retorno; } public void setState (string state) {this.state = state; }} CARETAKER DE CLASE {Private Memento Memento; Public Memento getMemento () {return Memento; } public void setmemento (Memento Memento) {this.memento = Memento; }} Cliente de clase pública {public static void main (String [] args) {Originator Originator = new Originator (); originator.setState ("Estado 1"); System.out.println ("Estado inicial:"+originator.getState ()); Caretaker Caretaker = nuevo Caretaker (); cuidada originator.setState ("status2"); System.out.println ("Estado después de cambiar:"+Originator.getState ()); originator.restoremento (cuidadero.getMemento ()); System.out.println ("Estado después de la recuperación:"+Originator.getState ()); }}El código demuestra un ejemplo de copia de seguridad única de un solo estado. La lógica es muy simple: la variable de estado en la clase de originador debe ser respaldada para que pueda restaurarse cuando sea necesario; En la clase Memento, también hay una variable de estado utilizada para almacenar la variable de estado temporal de la estado en la clase de originador; y la clase de cuidador se usa para administrar la clase de memorando, que se usa para escribir estados o recuperar estados en el objeto Memorandum.
Memo de múltiples respaldos de múltiples estados
En el ejemplo de la demostración del código general, la clase de originador tiene solo una variable de estado que necesita ser respaldada, aunque generalmente, el papel del iniciador suele ser un Javabean, hay más de una variables que deben respaldarse en el objeto, y más de un estado que necesita ser respaldado. Esta es una nota de múltiples respaldos de varios estados. Hay muchas formas de implementar notas. Hay muchas deformaciones y métodos de procesamiento para notas. Métodos como el código general generalmente no se usan. En la mayoría de los casos, las notas son copias de seguridad de varios estados y múltiples. De hecho, también es muy simple implementar múltiples estados y múltiples backup. El método más utilizado es agregar un contenedor de mapa al recuerdo para almacenar todos los estados y usar un contenedor de mapas en la clase de cuidador para almacenar todas las copias de seguridad. A continuación damos un ejemplo de múltiples estados y múltiples backup:
Originator de clase {String private state1 = ""; String private state2 = ""; String private state3 = ""; public String getState1 () {return state1; } 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 RestorementO (Memento Memento) {Beanutils.RestoreProp (this, Memento.getStateMap ()); } public String toString () {return "state1 ="+state1+"state2 ="+state2+"state3 ="+state3; }} class Memento {Map privado <String, Object> statEmap; public Mento (map <string, object> map) {this.stateMap = map; } mapa público <string, object> getStateMap () {return statEmap; } public void setStateMap (map <string, object> statEmap) {this.statemap = statEmap; }} class BeanUtils {public static map <String, Object> BackupProp (Object Bean) {Map <String, Object> Result = new HashMap <String, Object> (); intente {beaninfo beaninfo = introspector.getBeanInfo (bean.getClass ()); PropertyDescriptor [] descriptores = beaninfo.getPropertyDescriptors (); for (PropertyDescriptor des: Descriptors) {String fieldName = des.getName (); Método getter = des.getReadMethod (); Objeto fieldValue = getter.invoke (bean, nuevo objeto [] {}); if (! FieldName.equalSignorEcase ("class")) {result.put (fieldName, fieldValue); }}}} Catch (Exception e) {E.PrintStackTrace (); } resultado de retorno; } public static void RestoreProp (Object Bean, Map <String, Object> propMap) {try {beanInfo beanInfo = introspector.getBeanInfo (bean.getClass ()); PropertyDescriptor [] descriptores = beaninfo.getPropertyDescriptors (); for (PropertyDescriptor des: Descriptors) {String fieldName = des.getName (); if (propMap.ContainsKey (fieldName)) {método setter = des.getWriteMethod (); setter.invoke (bean, nuevo objeto [] {propMap.get (fieldName)}); }}} Catch (Exception e) {E.PrintStackTrace (); }}} CARETAKER DE CLASE {Mapa privado <String, Memento> MEMMAP = new HashMap <String, Memento> (); public Mento getMento (índice de cadena) {return memMap.get (index); } public void setmemento (índice de cadena, Memento Mento) {this.memmap.put (index, mento); }} Cliente de clase {public static void main (string [] args) {Originator ori = new Creator (); Caretaker Caretaker = nuevo Caretaker (); Ori.SetState1 ("China"); ori.setState2 ("fuerte"); ori.setState3 ("prosperidad"); System.out.println ("=== Estado de inicialización ===/n"+ori); Caretaker.setMemento ("001", ori.createMemento ()); ori.setState1 ("Software"); ori.setState2 ("estructura"); ori.setState3 ("excelente"); System.out.println ("=== estado modificado ===/n"+ori); ori.restoremento (cuidadero.getMemento ("001")); System.out.println ("=== estado restaurado ===/n"+ori); }} Las ventajas y desventajas del modo Memorandum y las ventajas del modo Memorandum para escenarios aplicables son:
Cuando el estado en el rol de iniciador cambia, puede ser un cambio incorrecto. Podemos restaurar este cambio incorrecto usando el modo memo.
El estado de la copia de seguridad se guarda fuera del rol de iniciador, por lo que el rol de iniciador no necesita administrar el estado de cada copia de seguridad.
Desventajas del modo memo:
En aplicaciones reales, el modo Memorandum es multi-estate y multi-backup. El estado del papel iniciador debe almacenarse en el objeto Memorandum, que consume recursos relativamente severamente.
Si necesita proporcionar operaciones de reversión, el uso del modo Memo es muy adecuado, como las operaciones de transacción JDBC, la recuperación CTRL+Z de los editores de texto, etc.