Antes de empezar, si no conoces a Pepe y su desafortunada historia, es porque todavía no leíste la primera parte de este artículo. Por lo cual, te lo dejo aquí.
Antes de Empezar
Es importante aclarar que los patrones de diseño son aplicables en el contexto del paradigma de la programación orientada a objetos (OOP). Si no conoces este término, tengo un artículo que lo explica a detalle y además lo compara con el paradigma de la programación estructurada (o procedimental).
Clasificación
Para entender cómo y cuál patrón de diseño aplicar a una determinada necesidad, debemos enfocarnos en sus tres tipos: Creacionales, Estructurales y de Comportamiento.
Los patrones creacionales son aquellos que se encargan de solucionar problemas que implican la creación de objetos, por lo tanto se centra en su instanciación. Esto nos permite manejar jerarquías de objetos complejas. Por ejemplo, imaginemos que tenemos que crear un videojuego RPG: Nuestro heroe esta en una parte del mapa; y necesitamos que aparezcan enemigos de forma aleatoria. Todos los enemigos tienen una clase Enemigo. Queremos que estas entidades aparezcan en tiempo real. El problema es que cuando necesitemos decidir qué enemigo utilizar, necesitamos generar condiciones en varias partes del código, dependiendo del tipo de enemigo. Esto se puede volver un problema mayor a medida que nuestro juego crece, porque por cada entidad tendremos que escribir nuevas condiciones. Este es un problema que resuelven los patrones creacionales, y para este caso concreto usaríamos Factory, el cual explicaremos más en detalle en los siguientes artículos.
Los patrones estructurales nos ayudan a la hora de relacionar objetos. Siguiendo el ejemplo anterior, nuestros enemigos heredan todos de la entidad Enemigo, por lo tanto podemos agruparlos y poder llamar a determinados eventos (atacar, moverse, usar algun poder) que impacte en todas las entidades a la vez. Ahora supongamos que uno de nuestros enemigos (una araña) genera otros a su alrededor (sus hijas). Estos son también entidades y tienen una dependencia directa con su creadora, la araña. Por lo tanto, si la araña madre muere, también queremos que lo hagan sus hijas (que mal suena eso). El problema es que si agregamos todas las entidades a una única lista global, perderemos esa referencia y no será posible generar este comportamiento. Para solucionarlo, existe un patrón llamado Composite, el cual nos permite trabajar de forma recursiva en la idea de que una entidad puede tener otras entidades dentro.
Los patrones de comportamiento nos ayudan a realizar interacciones entre objetos de forma que podamos distribuir las reponsabilidades de los mismos de una forma más optima. Apoyándonos en nuestro ejemplo integral, consideremos que cada enemigo tiene distintos modos de ataque: cuerpo a cuerpo, a distancia, entre otras. Podríamos crear una lógica de ataques dentro de la entidad Enemigo y luego utilizarla en cada uno, dependiendo del tipo que sea. El problema se genera cuando tenemos que agregar nuevos tipos de ataques; o necesitamos crear un enemigo que pueda atacar tanto a distancia como cuerpo a cuerpo. Tendríamos que estar refactoreando la lógica de nuestra clase principal y quizá copiar y pegar algunos comportamientos aplicables en distintos casos. Para esto existe un patrón llamado Strategy, el cual nos permite desacoplar el comportamiento de los ataques a una clase nueva que permita trabajar con una responsabilidad única (hay un poco de olor a principios SOLID en la sala) y darle esa lógica a nuestros enemigos según la necesiten.
Conclusiones
Espero que este resumen de cada clasificación te haya podido dar un panorama completo de como funcionan los patrones de diseño. No obstante, en los siguientes artículos vamos a tratar en profundidad cada uno de ellos.
Top comments (0)