2009-11-28 11 views
6

leí lo siguiente en un articledeshacer/rehacer con objetos inmutables

Los objetos inmutables son particularmente práctico de aplicación de determinadas expresiones comunes, tales como deshacer/rehacer y Abortables transacciones. Deshacer deshacer por ejemplo. Una técnica común para implementar deshacer es mantener una pila de objetos que de alguna manera sabe cómo ejecutar cada comando en reversa (el llamado "Patrón Comando"). Sin embargo, averiguar cómo ejecutar un comando en reversa puede ser complicado. Una técnica más simple es mantener una pila de objetos inmutables que representa el estado del sistema entre comandos sucesivos. Luego, para deshace un comando, simplemente revierte al estado anterior del sistema (y probablemente guarde el estado actual en la pila de rehacer).

Sin embargo, el artículo no muestra un buen ejemplo práctico de cómo los objetos inmutables podrían utilizarse para implementar operaciones de "deshacer". Por ejemplo ... eliminar 10 correos electrónicos de una bandeja de entrada de Gmail. Una vez que haces eso, tiene una opción de deshacer. ¿Cómo ayudaría un objeto inmutable en este sentido?

Respuesta

6

Los objetos inmutables mantendrían todo el estado del sistema, por lo que en este caso tendría el objeto A que contiene la bandeja de entrada original, y luego el objeto B que contiene la bandeja de entrada con diez correos electrónicos eliminados, y (en efecto) un puntero hacia atrás de B a A que indica que, si hace un "deshacer", entonces deja de usar B como el estado del sistema y comienza a usar A en su lugar.

Sin embargo, las bandejas de entrada de Gmail son demasiado grandes para usar esta técnica. Lo usaría en documentos que en realidad se pueden almacenar en una cantidad bastante pequeña de memoria, de modo que pueda mantener muchos de ellos para deshacer varios niveles.

Si desea mantener diez niveles de deshacer, puede ahorrar memoria guardando solo dos objetos inmutables, uno que es actual y uno que es de hace diez "undos" atrás, y una lista de Comandos que se aplicaron entre ellos.

Para hacer un "deshacer", vuelve a ejecutar todos menos el último objeto Command, utilízalo como el nuevo objeto actual y borra el último comando (o guárdalo como un objeto "Rehacer"). Cada vez que realiza una nueva acción, actualiza el objeto actual, agrega el Comando asociado a la lista y luego (si la lista tiene más de diez Comandos) ejecuta el primer Comando en el objeto desde el inicio de la lista de deshacer y tirar el primer Comando en la lista.

También puede hacer varios otros sistemas de puntos de control, que implican un número variable de representaciones completas del sistema, así como un número variable de Comandos entre ellas. Pero se aleja cada vez más de la idea original que usted citó y se vuelve más y más como un sistema mutable típico. Sin embargo, evita el problema de hacer Comandos consistentemente reversibles; solo necesita aplicar Comandos a un objeto hacia adelante y no hacia atrás.

SVN y otros sistemas de control de versiones son efectivamente una forma basada en disco o en red de deshacer y rehacer.

+3

"Las bandejas de entrada de Gmail son demasiado grandes para utilizar esta técnica". Ish. Si los mensajes reales son objetos separados, y los dos objetos diferentes de la bandeja de entrada se refieren a los mismos mensajes, entonces una bandeja de entrada es solo una lista y probablemente pueda hacerlo de esta manera. La otra gran cosa acerca de los objetos inmutables es que los objetos pueden compartir de manera segura recursos como este.Con los objetos mutables, es posible que tenga que preocuparse por los cambios en uno que aparezca incorrectamente en el otro. –

+1

Ese es un punto excelente. Observo que para una cuenta de GMail, el objeto inmutable apropiado sería la lista de etiquetas y las listas asociadas de objetos de correo electrónico para cada etiqueta; esto es mucho más pequeño que todo el archivo, pero mucho más grande que solo la lista de mensajes de la bandeja de entrada. – jprete

Cuestiones relacionadas