viernes, 22 de agosto de 2008
Patrones de diseño GoF (Gang of Four)
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
Genial…..como siempre este plan es simple……es magnífico……es perfecto…….pero!!!!!!!
martes, 8 de julio de 2008
El patrón "Memento" - Parte V
Por tanto la clase “MazingerZ” es:
Ya está todo listo para conquistar al mundo!!!!!!!!
Parte 6
sábado, 5 de julio de 2008
El patrón "Observer" (Observador) - Parte IV
El código sería algo así:
El código final sería algo así:
Esta historia continuara……
PARTE 5
jueves, 3 de julio de 2008
El patrón "Command" - Parte III
Pero como dará Cerebro la orden de atacar a sus tropas?.
Tanto la interfaz AccionSoldado como la clase RolSoldado no han cambiado.
Por tanto, al apretar el botón de "Al ataqueeeeeeeeeeeeeee" podría hacer algo así…..
En primer lugar, escribirá la siguiente interfaz:
Y los distintos comandos serán…..
sábado, 21 de junio de 2008
El patrón “Extension Objects” - Parte II
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
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……
jueves, 12 de junio de 2008
Inversion de Control (IoC)
…..y mejor ni pensemos si alguien se pone original (nunca faltan!!!!) y comience a modificar el constructor 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”.
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!!!).
- 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.
