sábado, 21 de junio de 2008

El patrón “Extension Objects” - Parte II

En el episodio anterior, Cerebro logro programar una máquina capaz de crear muchas copias de robots, logrando construir un gran ejército para CONQUISTAR AL MUNDO!!!.

Pero de repente, se dio cuenta que va a necesitar muchos robots del tipo “Mazinger Z” y también del tipo “El Vengador”, pero no todos los robots deberían tener el mismo rol. Por qué?. Bueno, dominar el mundo no es fácil. Hace falta organización. Hace falta un malvado plan!.

Entonces Cerebro ideo un plan. Quiere entrenar a algunos de sus robots como soldados para crear maquinas de matar sin misericordia!!!!.

Pero también quiere que otros robots trabajen en las fábricas haciendo armas, y también necesita que otro grupo de robots trabaje en la construcción de una fortaleza…….ufff.

Por lo tanto, se puede decir que necesita poder asignar distintos roles a los robots que ha construido.

Entonces, Cerebro comienza a pensar…….muy bien, ya tengo una clase que representa un robot “Mazinger Z”, pero ahora necesito tener un “Mazinger Z” que se comporte como un soldado, otro que se comporte como un fabricante, otro como constructor y lo mismo para “El Vengador”. Eso suena a "extender la funcionalidad de una clase", o no?....Brillante!!.

Escribiré una clase “MazingerZSoldado” que extienda a “MazingerZ”, y otra clase, “MazingerZFabricante”, que también extienda a “MazingerZ”.

Pero antes de ponerse a escribir código, Cerebro se da cuenta que probablemente esa no sea la mejor solución, porque cada vez que quiera asignar un nuevo rol a una robot, tendrá que escribir una nueva subclase (por ejemplo, una “MazingerZIngeniero”, o una “MazingerZConstructor”).

Además, el no sabe a priori cuantos roles va a necesitar asignar a un robot. Todo depende de lo que necesite en el futuro. Necesita dar soporte a la adición de interfaces desconocidas a la clase “MazingerZ”.

También se da cuenta que su primera forma de atacar el problema tiene otro punto débil, y es que no podrá re-asignar un rol. Si crea un “MazingerZSoldado”, tendrá esta para siempre, aunque la necesite para construir nuevos robots.

Pero también se da cuenta de otro punto débil, este es mucho más sutil. Una clase “MazingerZSoldado” y una “MazingerZ” son exactamente lo mismo. La única diferencia es que una de ellas tiene un comportamiento particular, pero en esencia, son lo mismo. Por tanto, no es muy apropiado representarlas utilizando clases distintas.

Cerebro está loco, pero no es tonto. Por tanto, decide que ha encontrado demasiados puntos débiles para su idea inicial, y que por tanto, es el momento de acudir al patrón “Extension Objects”.

Este patrón intenta anticipar la extensión de la interfaz de un objeto en el futuro (eso quiere decir: se pueden añadir interfaces a una clase en tiempo de ejecución). Así que empieza a leer, y a reírse. Y cuanto más lee, mas se ríe.

La idea es muy sencilla. Una clase (MazingerZ) será capaz de cambiar la interfaz que implementa en tiempo de ejecución, seleccionando esa interfaz de entre una colección de objetos ( los Extension Objects ). Cada uno de esos objetos encapsularan uno de los roles (MazingerZSoldado, MazingerZFabricante,... ).

Pero como será capaz la clase “MazingerZ“ de seleccionar la interfaz a implementar? Y de igual manera la clase “ElVengador”?. Bien, ambas clases implementaran la siguiente interfaz.



La clase “MazingerZ” implementa una interfaz para encapsular las acciones que implementa por ser un robot (mover la cabeza, mover las piernas, los brazos).



















Fíjense como la clase “MazingerZ” implementa el método “getExtension”, que elige la clase que debe devolver de entre una colección de roles (que son variables de la clase). Y los roles ?.

Para ese caso está la clase abstracta Rol (no he implementado nada en el, pero cualquier funcionalidad común a los roles debería implementarse aquí).



Pero Cerebro no es tonto, y sabe que en algún momento necesitara cambiar los roles de sus Robots. En algún momento puede llegar a necesitar que los robots que tienen el rol fabricante deban pasar a tener el rol soldado. Sería posible construir un “MazingerZ” con distintos tipos de roles, y que estos puedan ser modificados en cualquier momento?.

Entonces Cerebro luego de estudiar mejor el patrón “Extension Objects” decide refactorizar su código.







Ahora, los robots construidos por su máquina podrán cambiar su rol en tiempo de ejecución primero pueden ser soldados, luego fabricantes, mas tarde lo que a Cerebro le dé la gana).

Cerebro ha conseguido mantener la abstracción “MazingerZ” limpia de operaciones específicas para un robot. Eso también lo podría haber conseguido gracias a la herencia, definiendo las operaciones para los robots en las subclases, pero eso habría generado una jerarquía difícil de manejar.

Cerebro a dado un paso más en su plan de CONQUISTAR AL MUNDO!!!!!.

PARTE 3

3 comentarios:

Jc dijo...

jajajaj que bueno los post!

Anónimo dijo...

Bravo!!! excelente

Cristian Terrera dijo...

Excelentisimo post, gracias por tu aporte.