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

9 comentarios:

Anónimo dijo...

A esto llamo pedagogia,Felicidades!!

Unknown dijo...

Jajajajaja~! No habia visto ejemplo tan didáctico! Saludos...

Anónimo dijo...

Gracias por los comentarios. Esta semana continuo con la historia.

Anónimo dijo...

Exelente post. Tenes una gran didactica
Gracias

Chris dijo...

excelente post!

Anónimo dijo...

me parece que faltan detalles tecnicos.

ventajas/desventajas. . .

funcionalidades dependiendo del lenguaje...

aplicaciones informaticas concretas...

Unknown dijo...

Amigo gracias por este material...
(voy a continuar leyendo sobre los patrones de diseño)
Lo explicaste de manera minuciosa y entendible.
Una pregunta: Los patrones de diseño para Java EE son diferentes? o aplican estos mismos (perdona mi ignorancia... jeje)

Anónimo dijo...

Y yo leyendo el libro de la tribu de los 4... Je!!! enhorabuena por el articulo, Claro, didactico y divertido.

LLevo algun tiempo intentado resolver un ejerccicio en C++. Pero como hablamos de patrones entiendo que da igual el lenguaje. Lo propongo porque lo creo interesante...

Supongamos una clase mensaje. Esta clase tiene varios constructores. Buffer y tamaño, otro void, otro solo un buffer de tamaño fijo que es una cabecera...
void msg(char* pBuffer, DWORD dwSize)
void msg()
void msg(char* pHeader)

El mensaje tiene un tamaño maximo N. Que en principio esta harcodeado de forma que cuando se crea el objeto se comprueba que el buffer no exceda ese tamaño.

Ahora bien. LLega el listo del Jefe y te dice que eso no puede ir harcoded. Asi que Supongamos que Esta constante se lee de un fichero de configuracion. Asi todos los mensajes tendrian el mismo limite, pero este limite se podria variar segun necesidades del sistema.

Empieza el baile:

Si el fichero se lee en los constructores cada vez que se instancia una clase se va al fichero. Pero esto no mola porque es lento.

Si el cliente que construye el objeto le comuniqua un nuevo parametro que sea el tamaño limite. No mola porque entonces dejamos a la divina providencia el que todos los mensajes tengan el mismo limite.
y Ademas hay que cambiar el interfaz de los constructores.

¿Como resolver el dilema? habia pensado en usar una clase prototipo y establecer metodos para fijar lo que se fija en los constructores, mediante setters. Pero si tenemos digamos Nmil lineas de codigo creando mensajes no vamos a estar modificando el codigo. Gustariame por tanto algo mas elegante, una especie de superclase sobre el mensaje que tenga el limite. Quiza un decorator????

Anónimo dijo...

Eres un crack !!
Felicidades !