Mostrando entradas con la etiqueta Patrones de Diseño. Mostrar todas las entradas
Mostrando entradas con la etiqueta Patrones de Diseño. Mostrar todas las entradas

viernes, 22 de agosto de 2008

Patrones de diseño GoF (Gang of Four)

En anteriores post, hemos visto algunos de los patrones que son parte del GOF. Pero como una imagen vale más que mil palabras, aquí les dejo este link en donde podrán encontrar un excelente PDF con los diagramas UML de los principales patrones.

Esta no es la única opción, ya que también existe el poster de Head Fisrt Design Patterns, pero que a diferencia de la opción anterior, esta utlima es pagada.

Este es un poster que Cerebro no puede dejar de tener!!

domingo, 17 de agosto de 2008

El patrón “Cadena de Responsabilidad” (Chain of Responsibility) - Parte VI

Los últimos ataques han sido todo un éxito, cada día se logran nuevas conquistas!!!. Debido a esto, Cerebro se ha visto en la necesidad de aumentar el número de robots dentro de sus tropas. Ahora su ejército se encuentra organizado en una estructura jerárquica, para lo cual ascendió a sus mejores solados a rangos como “General” o “Coronel”.

Con esta nueva estructura será mucho fácil dar órdenes a su ejército, el simplemente dará la orden a su “General Mazinger Z” quien al leer el comunicado decidirá si debe ejecutarla el o deberá derivarla a un sub-alterno; y así sucesivamente en la jerarquía hasta llegar al “Soldado El Galactico”.

Genial…..como siempre este plan es simple……es magnífico……es perfecto…….pero!!!!!!!

Cerebro se ha dado cuenta nuevamente que ha olvidado algo muy importante, su mecanismo de comunicación (implementado con el patrón “Observador”) ya no le sirve. Ahora tiene una estructura jerárquica, y necesita que la orden pase a través de esta estructura hasta el sub-alterno al que se le desee enviar este mensaje. Por lo tanto necesita un mecanismo en el cual el receptor del mensaje pueda no solo ejecutar la orden, sino también poder comunicar esta a su sub-alterno en el caso de que no fuera dirigida a él.

Una solución sería ir replicando el patrón “Observador” en cada uno de sus niveles jerárquicos, pero esta no es la solución más optima..

Debido a todos estos problemas, recurre nuevamente a su gurú “Martin Fowler” y encuentra la solución perfecta!!!!. Cerebro ha visto que el patrón “Cadena de Responsabilidad” (Chain of Responsibility) es ideal para solucionar su problema.



Primero necesitara definir la clase “Mensaje”, la cual contendrá a quien esta dirigida la orden y cuáles son las instrucciones a ejecutar.



Luego, deberá definir la clase abstracta “EjecutarOrdenAltoMando”, la cual deberán extender cada uno de los elementos de su ejército.



Ahora, cada sub-alterno que extienda la clase abstracta, deberá definir un mecanismo que permita discriminar si la orden enviada la debe ejecutar el, o en caso contrario, enviar la orden a su sub-alterno.







Finalmente, será muy fácil para Cerebro enviar un mensaje a su ejército, el simplemente dará la orden a su “General” y listo!!



Cerebro lo ha conseguido nuevamente, ha logrado diseñar un nuevo mecanismo de comunicación para su ejército, continuando su malvado plan………“TRATAR DE CONQUISTAR AL MUNDO!!!!

martes, 8 de julio de 2008

El patrón "Memento" - Parte V

Cerebro se siente preparado para llevar a cabo su malvado plan. Tiene los conocimientos teóricos, tiene los conocimientos prácticos, pero hay tantos detalles que pulir antes de lanzarse a la conquista del mundo!.

En los ejemplos anteriores, hemos visto como Cerebro ha implementado el “Patron Prototype” (para crear su ejército de robots clones), el “Patron Extension Objects” (para asignarles sus roles), el “Patron Command” (para asignarles las ordenes), y el ”Patron Observer” (para implementar el sistema de comunicaciones). Parece que Cerebro ha estado bastante ocupado implementando patrones, pero ha sido suficiente?. NO!!.

Si recuerdan el “Patron Observer”, dejamos a los robots “Mazinger Z” y “El Vengador” en el instante previo al ataque final. Están esperando a recibir la orden de ataque. Cada robot esta alerta, escuchando la radio, esperando escuchar la señal secreta, para abandonar su posición y lanzarse a cumplir las órdenes recibidas.

Cerebro está a punto de presionar el botón de "Atacar", cuando de repente se da cuenta de que algo no está bien. Qué pasa si me veo obligado a dar la orden de retirada a mis tropas?. No es que mi plan vaya a fallar (después de todo soy un genio del mal), pero ya se sabe, no se puede confiar en los subordinados, y que pasa si tengo que cancelar el ataque cuando mis huestes ya han comenzado a avanzar?.

Ciertamente, Cerebro es un genio. Se ha dado cuenta de un sutil error en su plan. Qué pasaría si tiene que dar la orden de cancelar el ataque cuando sus tropas ya han abandonado su posición inicial?. Bueno, ha implementado un mecanismo de comunicaciones, así que puede mandar la señal secreta de retirada, no?. Pero hay un problema; los robots “Mazinger Z” y “El Vengador” no implementan un buen sistema del manejo de la memoria (sabía que no tenía que instalarles Windows!!!!).

La cuestión es complicada. Un robot “Mazinger Z” y “El Vengador” no tienen buen manejo de la memoria. Solo pueden recordar una cosa a la vez. Por tanto, pueden recordar que tienen que atacar, que tienen que moverse hacia algún lugar, pero en cuanto se meten esa información en la memoria no son capaces de recordar nada más.

Dicho de otra forma, Cerebro les puede decir que vuelvan a su posición original, pero eso no va a servir de nada, porque no se acuerdan de cuál era su posición original.

Peeeeeero, Cerebro recuerda vagamente, como entre una nebulosa, haber leído algo del “Patron Memento” de su gurú “Martin Fowler”.


Qué pasaría si cada robot “Mazinger Z” y “El Vengador” fuera capaz de escribir en un cuaderno su posición inicial, y entregara ese cuaderno a su Sargento?. Y si el Sargento guardara esos cuadernos, y se los entregara a sus propietarios en el caso de que necesitasen volver a las posiciones iníciales?. Problema resuelto!. Es perfecto!. Las ovejas y las vacas solo tendrán que recordar una posición (la posición hacia la que se supone que tiene que ir, sin importar si están atacando o están en retirada), mientras una entidad externa les guardara la información que necesitaran para retirarse.

Pero cómo puede un robot “Mazinger Z” o “El Vengador” guardar su información relevante en un cuaderno?. Fácil, cada robot será responsable de crear una instancia de la clase en la que se va a guardar su información interna, y la entregara a su sargento.



Un momento!. Cerebro se ha dado cuenta de que hay un punto débil en su plan. Si el Sargento guarda los cuadernos con las posiciones iníciales de los robots, hay riesgos de seguridad. Qué pasa si los enemigos roban esa información?. O incluso peor!!. Y si los enemigos no roban esa información, pero la sustituyen por información falsa?. Pero……un momento!. Si la información contenida en los cuadernos estuviera encriptado, o solo fuera accesible por los robots, el problema estaría resuelto, nadie podría cambiarla!.

Por tanto, para evitar posibles cambios en esa información, Cerebro va a tomar dos medidas drásticas. Por un lado, todos los valores guardados en la clase MazingerZMemento solo se podrán asignar a través del constructor. De ese modo, Cerebro se asegura que solo se podrán asignar al crear la clase, y nunca después.

Pero desgraciadamente, no es suficiente (es tan difícil conseguir un buen plan…uffff). Cerebro quiere evitar que la información guardada en el “Memento” sea modificada. De hecho, quiere que solo sea el robot “Mazinger Z” o “El Vengador”, el que pueda crear su memento correspondiente, y asignar sus valores. De esa forma, puede asegurarse de que nadie modifique esa información.

Hacer eso en Java es bastante fácil. Basta con colocar la clase MazingerZMemento en el mismo package que la clase "MazingerZ", y hacer tanto su constructor como sus variables de clase protected. De esa forma, solo pueden crear instancias de esa clase otras clases que estén en su mismo paquete.

Por tanto la clase “MazingerZ” es:







Cerebro lo ha conseguido de nuevo!!. Ha sido capaz de encapsular el estado interno de un objeto en otro objeto distinto, y encapsularlo tan bien que ese segundo objeto solo puede ser utilizado por el objeto que lo creo.

Ya está todo listo para conquistar al mundo!!!!!!!!

Parte 6

sábado, 5 de julio de 2008

El patrón "Observer" (Observador) - Parte IV

Esta desencadenado!!!!! El primer ataque ha sido lanzado. Cerebro ha dado las órdenes a sus tropas para dominar el mundo.

En los ejemplos anteriores hemos visto como Cerebro ha conseguido clonar cualquier robot utilizando un “Patron Prototype”, ha conseguido darles un rol dinámicamente con el “Patron Extension Objects”, y ha repartido las ordenes con un “Patron command”.

Pero como ya sabemos, Cerebro está loco, pero no es tonto. Sabe, que algo puede salir mal, que un pequeño detalle puede destruir sus planes de dominar el mundo. Pero también sabe que una retirada a tiempo es una victoria.

Por lo tanto, ha equipado a sus tropas de una radio de comunicaciones. Pero, porque ha hecho esto?. Sencillo, en el fragor de la batalla, las comunicaciones directas se hacen complicadas. Es difícil hacer llegar las ordenes, y muchas veces no se tiene claro a quien le estamos dando esas órdenes ( será a “Mazinger Z” o “El Vengador”? ). Conquistar el mundo no es fácil, de hecho muchos lo han intentado pero no lo han conseguido.

Cerebro ha estudiado con detenimiento todos los intentos anteriores para no reproducir los mismos errores que otros han cometido. Qué pasaría si para dar nuevas órdenes, necesitase que el sargento “Mazinger Z” tuviese que recorrer la trinchera indicando uno por uno a todos los robots que se retirasen?. Desde que le diese la orden al primer robot, hasta que se la diese al último, pasaría un tiempo precioso. Además, y si ocurre algo por el camino?. Las posibilidades de que las órdenes no lleguen a todos los integrantes de la tropa son amplias.

Sabiendo esto, Cerebro recurre nuevamente a su gurú “Marin Fowler” y decide hacer un cambio fácil y rápido el comportamiento de sus tropas, utilizando el “Patron Observer”.



Como Cerebro no es tonto, ha encontrado una malvada forma de enviar las órdenes a sus tropas. Los robots “Mazinger Z” y “El Vengador”, estarán equipados con una radio que sintoniza “La señal del mal”. Sus tropas estarán atentas a la radio, y cuando esta emita una canción de “Metallica” les indicara que acción deben tomar.

El código sería algo así:















De este modo, Cerebro se puede comunicar rápidamente con todas sus tropas. Es brillante, es genial, es maravilloso, es.........perfecto?. Bueno, la verdad es que está muy bien, pero imaginemos por un momento, una situación en la que un robot consigue infiltrarse en el alto mando enemigo, y descubre que el enemigo está a punto de ser derrotado, y justo en ese momento de éxtasis, la radio emite “The Call of Ktulu" (la canción que indica a las tropas que hay que retirarse).

NOOOOOOOOO (bueno, esto está traducido, claramente, un robot diría algo así como BEP-BEP-BEP). Nuestro robot espía, tiene una información valiosísima, pero que no puede comunicar a su alto mando, porque la forma de transmisión es únicamente de tipo “Push” (desde Cerebro a sus tropas), por lo que no hay retorno.

Qué situación, el robot necesita transmitir que el ataque debe continuar pero......jajajajajajajaja, Cerebro ha pensado en ello, y ha decidido implementar un “Patron observer” que permita la transmisión tipo “Push” (del sujeto emisor a todos los sujetos receptores) y tipo “Pull” (uno de los objetos receptores, puede solicitar una información al objeto emisor para que este la envié a todos los demás). Así, nuestro robot espía, estará equipado con un número de teléfono al que podrá llamar y solicitar que emitan "Master of Puppets", y cuando esta canción sea emitida por la radio, los robots “Mazinger Z” y “El Vengador” que la escuchen, sabrán que ha llegado el momento de la ofensiva final!!!. Para ello, Cerebro deberá modificar ligeramente su código.

El primer paso será que nuestro sujeto, implementara un nuevo método que hemos añadido a la interfaz Sujeto( solicitarInformacion ), que permitirá recibir las llamadas telefónicas del robot espía. Veremos también que el constructor de los robots “Mazinger Z” y “El Vengador” también ha cambiado un poco. Ahora estos robots, almacenaran una referencia al constructor. También modificaremos el código de nuestro robot “Mazinger Z” (suponemos que este será el robot espía en el momento en que decide que pese a lo que emite la radio, hay que atacar y pide que se emita “Master of Puppets” que es otra señal de ataque ).

El código final sería algo así:











Evidentemente, Cerebro que ha estudiado la API de JAVA y sabe que existe la clase java.util.Observable y la interface java.util.Observer. La primera no la ha utilizado, pues eso implicaría que Cerebro extienda o herede de “Observable”. Esto podría ser posible, pero en realidad Cerebro extiende de una larga extirpe de profesores diabólicos empeñados en conquistar el mundo, y ni quiere ni puede extender de Observable. ( class Cerebro extends ExtirpeDeProfesoresDiabolicos, Observable --> esto no es posible ). Por eso ha decidido construirse su propia interface “Sujeto”.

Con respecto a la interface java.util.Observer, si la podría haber utilizado para que sus robots “Mazinger Z” y “El Vengador” la implementasen en lugar de implementar “Observador”, pero ya saben, los genios del mal les gusta hacer las cosas a su manera.

Esta historia continuara……

PARTE 5

jueves, 3 de julio de 2008

El patrón "Command" - Parte III

Todo está preparado. Cerebro ya cuenta con un gran número de copias de los robots “Mazinger Z” y “El Vengador”. Además, ha asignado los roles a cada uno de estos. Es el momento perfecto para que Cerebro lance su ataque final. Ha llegado el momento de conquistar el mundo!!!!

Pero como dará Cerebro la orden de atacar a sus tropas?.

Cerebro está loco, pero no es idiota. Quiere conquistar el mundo, para lo cual ha ideado un plan malvado perfecto!!!. Pero sabe que tener un buen plan (aunque sea malvado) no es una garantía para el éxito. Necesita un plan de emergencia.

Cerebro quiere que algunos de sus robots soldados participen en el primer (y por tanto, glorioso) ataque. Pero también quiere reservar unos cuantos robots soldados y dejarlos descansando, mientras sus colegas son masacrados en el campo de batalla, para que puedan ser utilizados como refuerzos.

Pero, como podrá hacerlo?. Cerebro es un genio muuuuuy ocupado, por lo tanto el ataque debe poder ser lanzado sin mucha intervención de su parte. Algo tan simple como apretar el botón de "Dominar el Mundo" sería perfecto. Es rápido, es fácil, y Cerebro puede delegar la tarea incluso a Pinky.

Eso sería perfecto, pero para conseguirlo tiene que encontrar la forma de poderle decir a cada robot que es lo que se supone que debe hacer cuando el "glorioso momento del ataque" llegue.
Pero cómo ?. El unico conocimiento que tiene Cerebro de los robots soldados es su interfaz, porque sabe que cada robot soldado implementa la interfaz AccionSoldado.

Resumiendo, lo que en realidad necesita es que algunos robots ejecuten uno de los métodos de AccionSoldado, y otros robots ejecuten uno distinto cuando reciban la orden de atacar.





Tanto la interfaz AccionSoldado como la clase RolSoldado no han cambiado.

Cerebro ha logrado crear diez mil robots soldados, y diez mil robots fabricantes, utilizando dos arrays para almacenar una referencia a todos ellos.

Por tanto, al apretar el botón de "Al ataqueeeeeeeeeeeeeee" podría hacer algo así…..



Cerebro está loco, pero no es un tonto. No le gusta la solución que ha encontrado. Por que?. Bueno, no es exactamente lo que quería. Cerebro simplemente quiere poder decir "Al ataqueeeeeeeee", y comenzar a reírse histéricamente mientras los robots se lanzan ciegamente a cumplir sus órdenes.

Cerebro sospecha que todo podría ser mucho más fácil si pudiera darle a cada uno de los robots un sobre conteniendo sus órdenes. Cuando el "Momento de gloria" llegue, simplemente le tendría que decirle a cada robot que habrá el sobre y obedezca las ordenes contenidas en el. Pero él no quiere saber de qué forma tienen que cumplir esas órdenes los robots, de hecho, ni siquiera quiere saber si le está mandando algo a un robot “Mazinger Z” o “El Vengador”, o a lo que sea.

Pero justo en ese momento, comienza a reírse con más fuerza que nunca. Porque ha recordado el patrón Command.



Cerebro quiere dar cuatro órdenes diferentes. Dos para ser obedecidas por los robots soldado ("ataca", y "espera hasta recibir nuevas órdenes"), y las otras dos dirigidas a los robots fabricantes ( "comienza a construir la fortaleza", y "diseña armas" ).

Para esto, va a encapsular la orden y el receptor de dicha orden, en un paquete ( el sobre ). Cómo?....

En primer lugar, escribirá la siguiente interfaz:



Y los distintos comandos serán…..











Por tanto, cuando Cerebro presione el botón de "al ataqueeeeeeeeee", tendrá que hacer un método algo así:



Este método recibe como parámetro un array conteniendo todos los comandos. Ese array se podría construir con un código similar a este…..



El código es horrible, pero sirve para ilustrar como Cerebro ha creado una colección de objetos, cada uno de los cuales encapsula un comando y el receptor de dicho comando.

Ahora, Cerebro no necesita saber nada acerca de esos comandos, ni del receptor de los mismos. Simplemente tiene que decir "ejecutar el comando!!", y el comando hará el resto.

De hecho, Cerebro ha conseguido desacoplar tres procesos diferentes: la creación de los objetos (implementando el patrón Prototype ), la asignación de roles a esos objetos ( con el patrón Extension Objects ), y la forma en que esos roles pasan a la acción ( el patron Command ).

Con esto, ha dado un paso más en su malvado plan de CONQUISTAR AL MUNDO!!!!!

PARTE 4

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

domingo, 15 de junio de 2008

El patron prototype (prototipo) - Parte I

De la literatura relacionada con patrones de diseño, hay dos libros que recuerdo haber leído con mucho agrado (esos libros que cuesta dejar de leerlos). Uno de ellos es el “Head First Design Patterns”, el cual realmente me rompió los esquemas de los libros que hasta el momento había leído por la forma en que presenta cada uno de los patrones. El otro libro es el “Design Patterns for Dummies”, que para este caso su título lo dice todo.
Hace un tiempo atrás, necesitaba hacer una clase de patrones de diseño en una universidad, y fue del primer libro, de donde saque muchas ideas para enseñar algunos patrones básicos.
El primer patrón que veremos será el “Prototype”, pero siguiendo la filosofía del “Head First Design Patterns” en la simpleza de enseñar patrones.

Para lograr esto, el protagonista principal de estos post sera…..

Como todos sabemos, Cerebros es un ratón cuyo único deseo es llevar a cabo su malvado plan para…..DOMINAR AL MUNDO!!!!.

Una mañana, ideo un plan malévolo pero perfecto!!!. Recordando su niñez cuando veía el “Show de los Robots” o “Pipiripao” (uff……que viejo), decidió construir un ejercicito de robots y así dominar el mundo!!!!. Para lograr su objetivo, debía construir una máquina capaz de construir cualquier tipo de robot y que fuera programada en Java.

Así que comenzó a programar su máquina para construir su primer robot:





Tras construir un ejército de robots, Cerebro de dio cuenta que construir un ejército de robots tipo “El Vengador” unidos a los “Mazinger Z” le ayudaría a dominar el mundo más rápido.

Pero aquí se le presento el primer problema. Su máquina no fue programada para construir “El Vengador”, sino solamente para construir “Mazinger Z”.

Así que Cerebro, como buen programador, decide refactorizar su código para añadir a su máquina la funcionalidad necesaria para construir “El Vengador”.




Cerebro está loco, pero no es tonto. Por tanto, enseguida se da cuenta de que puede encontrarse con problemas si decide construir otro tipo de robots como “El Gran Dragón del Espacio” o “Afrodita A”.

Tras pensar cuidadosamente sobre su problema, decide hacer una nueva refactorización a su código.





Tras varios minutos de las típicas risas histéricas de Pinky, Cerebro comienza a darse cuenta que la forma en que ha programado su máquina tiene bastantes puntos débiles.


En primer lugar, el método “construirRobot” devuelve un Object, no un “Mazinger Z” o un “El Vengador”. Por qué?....porque ese método no sabe lo que va a crear a priori. Cerebro se da cuenta que esta no es la mejor solución.


También se da cuenta que si en algún momento quisiera construir algún otro tipo de robot, debería programar nuevamente su máquina, lo cual la transforma, en una maquina difícil de mantener.


Pero entonces, una idea empieza a abrirse paso en su malvado cerebro. Aun no sabe exactamente cómo hacerlo, pero que pasaría si pudiera darle algo a la maquina (un robot del tipo Mazinger Z, El Vengador, Afrodita A, etc…) y pedirle a la misma que le entrege 800 copias del mismo?....brillante!!!. Así, no tendría que preocuparse de cómo funciona la maquina, simplemente esta devolvería tantas copias como necesite del original.


Entonces cerebro recuerda haber estudiado el patrón “Prototype”. Para lograr esto, la maquina no puede saber que tiene que construir ni cómo debe construirlo (la creación de la copia), y tampoco puede ser una responsabilidad de cada uno de los robots (o cosas a copiar). La maquina, simplemente debe recibir un robot y le dirá a este que produzca tantas copias de el mismo como se necesiten y luego las devolverá.




De hecho, Cerebro se ha dado cuenta de que la forma en la que deben crearse las nuevas copias de los robots no ha de ser la misma para todos, sino que en algunos casos le va a interesar utilizar el mecanismo de clonado de Java, y en otros tener un control más fino del mismo.

Así que, la primera tarea de Cerebro será crear una interfaz (que extiende Cloneable, implementando de este modo el método clone()), que será el que implemente cada uno de los robots.






También sería posible que todos los robots extendieran de una clase base, y que por lo tanto el tipo que devuelve el método duplicar() fuera esa clase base. Pero de la manera anteriormente comentada el diseño es mucho más flexible.


El método duplicar() será el encargado de crear y devolver una nueva copia de cada robot que lo implemente.












Ahora, Cerebro puede seguir construyendo su ejército para conquistar el mundo el mundo con los clones creados por su máquina, sabiendo que puede crear copias de todo lo que le dé la gana, porque le ha dado a su máquina el “don” de crear objetos sin saber de qué tipo deben ser.


Pero Cerebro es un hombre de ciencia, y en su afán por alcanzar el conocimiento absoluto, sigue leyendo la documentación sobre el patrón prototype, y entonces se da cuenta de que también ha separado el código que crea los objetos del código que maneja los detalles de la creación de nuevos objetos.


Esta historia continuara……

Parte 2

jueves, 12 de junio de 2008

Inversion de Control (IoC)

Hace un tiempo atrás convencí a un amigo de que aprendiera Spring, contándole de todas las ventajas que podría lograr utilizando este framework. El comenzó a estudiarlo y como a todos nos ha pasado, le sorprendió la facilidad con la que puede desarrollar aplicaciones.
Hasta ahí todo iba muy bien, pero cuando le pregunte que le pareció la “inversión de control” y la “inyección de dependencia”, me dijo que lo único que entendía era que Spring utilizaba estos patrones…...pero de que se trataba……ni idea!!!!
Así que mi querido amigo XXX (no te voy a echar al agua)…...este post es para ti.
Imaginemos que tenemos una clase “Componente” que necesita usar la clase “Servicio”. Una solución para esto podría ser :







El problema de esto es que estamos acoplando las clases. Qué pasaría si por algún requerimiento, el desarrollador modifica el código, solicitando ahora algún parámetro en el constructor de la clase “Servicio”?. Esto nos llevaría no solo a modificar el código de la clase “Servicio”, sino también el de la clase “Componente”.
O pero aun, tu jefe te dice que no le gusta como esta implementada la clase “Servicio”, así que él, en un acto de iluminación divina, desarrollo la clase “Servicio2” la cual (supuestamente) es mejor a la anterior. Por lo tanto, nuevamente tendremos que modificar nuestra clase “Componente”:







…..y mejor ni pensemos si alguien se pone original (nunca faltan!!!!) y comience a modificar el constructor de la clase “Servicio2”.
Pero como nada es tan terrible, una solución para estos casos es la “Inversión de control”.
El primer cambio que tendremos que hacer a nuestro código, es olvidarnos de usar “new XXX()”, para lo cual definiremos un método “setXXX” que nos pase una referencia de una instancia de la clase “Servicio2” :







Hasta aquí todo va bien, pero que pasaría si nuestro jefe, en un acto de arrepentimiento te dice “evaluando la situación, pienso que debemos volver a usar la clase “Servicio” hasta que nuevo aviso (por no decir, hasta que arregle los errores en mi código)”, y nosotros que ya pensábamos que teníamos casi todo controlado, nuevamente tendremos que volver a cambiar el código de la clase “Componente”, modificando el atributo y el método “setXXX”.
Pero como buenos programadores, sabemos que no va a faltar el jefe original que se le ocurra volver a cambiar el servicio, así que, para evitar problemas a futuro, definiremos una interfaz para el servicio. De ahora en adelante, cualquier clase servicio que se le pase a la clase “Componente”, deberá implementar esta interfaz (ufff….ya no deberemos tocar el código de la clase “Componente”).











Como vemos, cambiar el tipo de servicio en la clase “Componente” ya no tiene impacto en nuestro código!!!! (Obviamente..…hasta que no falte el original que cambie la interfaz!!!).
Hasta aquí toda esta correcto, pero nos falta un pequeño elemento, el “Ensamblador”, cuya tarea principal es obtener la información de cómo cada uno de los elementos debe ser inyectado en otros elementos.
Para estos casos, es donde frameworks como PicoContainer o Spring utilizan el patrón “Inversión de Control”, los cuales se encargan de realizar la inyección de los elementos. El como lo hacen, puede ser a través de código o en un archivo de configuración.
Para el caso de la “Inyección de dependencias” existen tres mecanismos:
  • Inyección de Interfaz (IoC tipo 1)
  • Inyección de Setter (IoC tipo 2)
  • Inyección de Constructor (IoC 3)

Que diferencias existen entre los distintos tipos de inyección, va mas allá de este post, pero el señor Martin Fowler lo explica muy bien en este articulo.

La inversión de control no es la única forma de solucionar este problema, también existe el patrón “Service Locator”, pero eso es tema para otro post.