Patrones de Diseño

Share on Facebook0Share on LinkedIn0Tweet about this on TwitterShare on Google+0Email this to someonePrint this page

Los mejores diseñadores en cualquier campo tienen una habilidad extraña para reconocer patrones que caracterizan un problema y los patrones correspondientes, que pueden combinarse para crear una solución.

Durante el proceso del diseño orientado a objetos, un ingeniero del software debe observar cada oportunidad en la que pueda reutilizar patrones de diseño existentes (cuando cumplen las necesidades del diseño), en vez de crear otros nuevos.

Antes de examinar los patrones con detalle vale la pena observar un ejemplo sencillo de un patrón, que se presenta una y otra vez. Muchas aplicaciones tienen el requisito de que solo una instancia de un solo objeto debe ser instanciada. Algunos ejemplos de aplicaciones y objetos de instancias simples son:

  • En un sistema operativo habrá solo un objeto administrador de tareas, que mantiene el registro de los procesos del sistema y usuario. Solo existirá una instancia de ese administrador de archivos.
  • En un sistema de control de tráfico aéreo, solo existirá una instancia controladora que mantiene los registros de los planes de vuelo y sus posiciones.
  • En una aplicación bancaria solo deberá existir un proceso orquestador que deberá mantener la sincronización de los canales de comunicación como cajeros automáticos.

Entonces, ¿qué es un patrón de diseño?

Un patrón de diseño es una solución a un problema específico y común en el diseño orientado a objetos. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reusable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.

Los patrones de diseño empezaron a reconocerse a partir de las descripciones de varios autores a principios de 1990. Este reconocimiento culmina en el año 1995 con la publicación del libro Design Patterns: Elements of Reusable Object-Oriented Software de Gamma, Helm, Johnson y Vlissides conocidos como la Pandilla de los Cuatro (Gang of Four); este libro puede considerarse como el más importante realizado sobre patrones de diseño hasta el momento.

Clasificación de los patrones de diseño

En el libro, los autores clasificaron los patrones de diseño en los siguientes grupos:

Patrones de creación

  • Abstract Factory. Proporciona una interfaz para crear familias de objetos o que dependen entre sí, sin especificar sus clases concretas.
  • Builder. Separa la construcción de un objeto complejo de su representación, de forma que el mismo proceso de construcción pueda crear diferentes representaciones.
  • Factory Method. Define una interfaz para crear un objeto, pero deja que sean las subclases quienes decidan qué clase instanciar. Permite que una clase delegue en sus subclases la creación de objetos.
  • Prototype. Especifica los tipos de objetos a crear por medio de una instancia prototípica, y crear nuevos objetos copiando este prototipo.
  • Singleton. Garantiza que una clase sólo tenga una instancia, y proporciona un punto de acceso global a ella.

Patrones estructurales

  • Adapter. Convierte la interfaz de una clase en otra distinta que es la que esperan los clientes. Permiten que cooperen clases que de otra manera no podrían por tener interfaces incompatibles.
  • Bridge. Desvincula una abstracción de su implementación, de manera que ambas puedan variar de forma independiente.
  • Composite. Combina objetos en estructuras de árbol para representar jerarquías de parte-todo. Permite que los clientes traten de manera uniforme a los objetos individuales y a los compuestos.
  • Decorator. Añade dinámicamente nuevas responsabilidades a un objeto, proporcionando una alternativa flexible a la herencia para extender la funcionalidad.
  • Facade. Proporciona una interfaz unificada para un conjunto de interfaces de un subsistema. Define una interfaz de alto nivel que hace que el subsistema se más fácil de usar.
  • Flyweight. Usa el compartimiento para permitir un gran número de objetos de grano fino de forma eficiente.
  • Proxy. Proporciona un sustituto o representante de otro objeto para controlar el acceso a éste.


Patrones de comportamiento

  • Chain of Responsibility. Evita acoplar el emisor de una petición a su receptor, al dar a más de un objeto la posibilidad de responder a la petición. Crea una cadena con los objetos receptores y pasa la petición a través de la cadena hasta que esta sea tratada por algún objeto.
  • Command. Encapsula una petición en un objeto, permitiendo así parametrizar a los clientes con distintas peticiones, encolar o llevar un registro de las peticiones y poder deshacer la operaciones.
  • Interpreter. Dado un lenguaje, define una representación de su gramática junto con un intérprete que usa dicha representación para interpretar las sentencias del lenguaje.
  • Iterator. Proporciona un modo de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación interna.
  • Mediator. Define un objeto que encapsula cómo interactúan un conjunto de objetos. Promueve un bajo acoplamiento al evitar que los objetos se refieran unos a otros explícitamente, y permite variar la interacción entre ellos de forma independiente.
  • Memento. Representa y externaliza el estado interno de un objeto sin violar la encapsulación, de forma que éste puede volver a dicho estado más tarde.
  • Observer. Define una dependencia de uno-a-muchos entre objetos, de forma que cuando un objeto cambia de estado se notifica y actualizan automáticamente todos los objetos.
  • State. Permite que un objeto modifique su comportamiento cada vez que cambia su estado interno. Parecerá que cambia la clase del objeto.
  • Strategy. Define una familia de algoritmos, encapsula uno de ellos y los hace intercambiables. Permite que un algoritmo varíe independientemente de los clientes que lo usan.
  • Template Method. Define en una operación el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos. Permite que las subclases redefinan ciertos pasos del algoritmo sin cambiar su estructura.
  • Visitor. Representa una operación sobre los elementos de una estructura de objetos. Permite definir una nueva operación sin cambiar las clases de los elementos sobre los que opera.

Cuando no utilizar patrones de diseño

La primera regla de los patrones de diseño coincide con la primera regla de la optimización: retrasar. Del mismo modo que no es aconsejable optimizar prematuramente, no se deben utilizar patrones de diseño antes de tiempo.

Seguramente sea mejor implementar algo primero y asegurarse de que funciona, para luego utilizar el patrón de diseño para mejorar las flaquezas; esto es cierto, sobre todo, cuando aún no ha identificado todos los detalles del proyecto (si comprende totalmente el dominio y el problema, tal vez sea razonable utilizar patrones desde el principio, de igual modo que tiene sentido utilizar los algoritmos más eficientes desde el comienzo en algunas aplicaciones).

Los patrones de diseño pueden incrementar o disminuir la capacidad de comprensión de un diseño o de una implementación, disminuirla al añadir accesos indirectos o aumentar la cantidad de código, disminuirla al regular la modularidad, separar mejor los conceptos y simplificar la descripción. Una vez que aprenda el vocabulario de los patrones de diseño le será más fácil y más rápido comunicarse con otros individuos que también lo conozcan. Por ejemplo, es más fácil decir “ésta es una instancia del patrón Visitor” que “éste es un código que atraviesa una estructura y realiza llamadas de retorno, en tanto que algunos métodos deben estar presentes y son llamados de este modo y en este orden”.

La mayoría de las personas utiliza patrones de diseño cuando perciben un problema en su proyecto —algo que debería resultar sencillo no lo es — o su implementación— como por ejemplo, el rendimiento.

Examine un código o un proyecto de esa naturaleza. ¿Cuáles son sus problemas, cuáles son sus compromisos? ¿Qué le gustaría realizar que, en la actualidad, es muy difícil lograr? A continuación, compruebe una referencia de patrón de diseño y busque los patrones que abordan los temas que le preocupan.

Como ya he mencionado la referencia más utilizada en el tema de los patrones de diseño es el libro Design Patterns: Elements of Reusable Object-Oriented Software de Gamma, Helm, Johnson y Vlissides.

En un próximo artículo pasaré a explicar la implementación de los patrones de diseño Abstract Factory y Singleton.