Uso de Patrones de diseño

LIBP-0342 (Libro de pautas)

Según las características de la aplicación a desarrollar y los problemas surgidos durante el diseño, serán aplicables distintos patrones de diseño.

Pautas

TítuloCarácter
AdaptadorRecomendada
Cadena de ResponsabilidadesRecomendada
ComandoRecomendada
CompositeRecomendada
ConstructorRecomendada
DecoradorRecomendada
EstadoRecomendada
EstrategiaRecomendada
FachadaRecomendada
FactoríaRecomendada
Factoría AbstractaRecomendada
IntérpreteRecomendada
IteradorRecomendada
MediadorRecomendada
MementoRecomendada
MVCRecomendada
ObservadorRecomendada
Peso LigeroRecomendada
PlantillaRecomendada
PrototipoRecomendada
ProxyRecomendada
PuenteRecomendada
SingletonRecomendada
VisitorRecomendada
WizardRecomendada

Adaptador

Crear una nueva clase que será el Adaptador, que extienda del componente existente e implemente la interfaz obligatoria

El patrón Adaptador convierte la interfaz de una clase en otra interfaz para adaptarla a las necesidades de un desarrollo concreto.

Para realizar una implementación correcta del patrón se recomienda crear una nueva clase que será el Adaptador, que extienda del componente existente e implemente la interfaz obligatoria. De este modo tenemos la funcionalidad que queríamos y cumplimos la condición de implementar la interfaz

El uso de este patrón es recomendable en los siguientes casos:

  • Si se quiere reutilizar una clase pero su interfaz no concuerda con nuestras necesidades.
  • Cuando se desea crear una clase reutilizable que coopera con clases no relacionadas, es decir, clases que no tienen necesariamente interfaces compatibles.
  • Cuando se quiera utilizar un componente de caja negra.

Cadena de Responsabilidades

Implementar la cadena sucesora

El patrón de diseño Cadena de responsabilidades permite establecer una cadena de objetos receptores a través de los cuales se pasa una petición formulada por un objeto emisor.

Es recomendable usar este patrón cuando:

  • Más de un objeto necesita manejar una respuesta y el manejador no es conocido a priori.
  • Se quiere poder realizar una petición sin conocer a quién hay que solicitarlo.
  • El conjunto de objetos que pueden procesar una respuesta pueden ser especificados de forma dinámica.

Comando

Determinar cómo de inteligente debe ser el comando y cómo implementar las operaciones de vuelta atrás y rehacer

Este patrón permite solicitar una operación a un objeto sin conocer realmente el contenido de esta operación, ni el receptor real de la misma.

El patrón Comando puede usarse con los siguientes objetivos:

  • Parametrizar objetos mediante una acción
  • Especificar, encolar y ejecutar peticiones en distintos momentos (el objeto Comando tiene un tiempo de vida distinto al de la petición)
  • Independizar el momento de petición del de ejecución.
  • Mantener operaciones que permitan deshacer la petición.
  • Acciones que permitan la recuperación del sistema.
  • Interfaz común que permita invocar las acciones de modo uniforme y extender el sistema de modo sencillo.

Composite

Establecer referencias explícitas a los padres, compartir componentes, maximizar la interface del componente, tener en cuenta el orden de los hijos y declarar las operaciones de manejo de hijos

El patrón Composite sirve para construir objetos complejos a partir de otros más simples y similares entre sí, gracias a la composición recursiva y a una estructura en forma de árbol.

Se recomienda el uso del patrón si:

  • Se quiere realizar jerarquías de objetos del tipo "todo-parte"
  • Se quiere ser capaz de ignorar la diferencia entre los objetos individuales y composiciones de objetos. Los clientes tratarán a todos los objetos de la estructura compuesta uniformemente.

Constructor

Crear la interfaz lo suficientemente general para permitir la construcción de todo tipo de objetos de los constructores concretos

El patrón Constructor es usado para permitir la creación de una variedad de objetos complejos desde un objeto fuente. En el caso común, los productos producidos por constructores concretos difieren mucho en su representación, esto es mas difícil de manejar mediante el uso de clases abstractas.

Se debe usar este patrón si se quiere:

  • Que el algoritmo para la creación de objetos complejos sea independiente de las partes que construyen el objeto y cómo son ensambladas.
  • Que el proceso de construcción pueda tener diferentes representaciones para el objeto que está construido.

Decorador

Un componente y su decorador deben compartir la misma interfaz

El patrón Decorador responde a la necesidad de añadir dinámicamente funcionalidad a un objeto. Se puede omitir la clase abstracta Decorador si solo se va a definir una responsabilidad.

Se recomienda el uso del patrón cuando se quiere:

  • Añadir responsabilidades a objetos concretos de manera dinámica y transparente, esto es, sin afectar a otros objetos.
  • Para el tratamiento de responsabilidades que se pueden otorgar o derrogar.
  • Cuando la herencia sea muy compleja porque implique la creación de múltiples subclases para dar completitud a todas las combinaciones posibles.

Estado

Definir las transiciones dentro de la clase Contexto cuando el criterio a aplicar para la transición de un estado a otro es fijo

El patrón Estado se utiliza cuando el comportamiento de un objeto cambia dependiendo del estado del mismo. El patrón no indica exactamente dónde definir las transiciones de un estado a otro. Existen dos formas de solucionar esto: Una es definiendo estas transiciones dentro de la clase Contexto, la otra es definiendo estas transiciones en las subclases de Estado. Es más conveniente utilizar la primer solución cuando el criterio a aplicar es fijo, es decir, no se modificará. En cambio la segunda resulta conveniente cuando este criterio es dinámico, el inconveniente aquí se presenta en la dependencia de código entre las subclases.

Se recomienda el uso del patrón si:

  • El comportamiento de un objeto depende del estado en el que se encuentra y este estado se modifica en función de las transiciones de estado.
  • Si existen muchas operaciones con la misma lógica, el patrón permite introducir esta lógica en una clase separada.

Estrategia

Definir la comunicación entre el Contexto y la Estrategia

Se puede optar por que el Contexto pase sus datos como argumento de las operaciones de la Estrategia (bajo acoplamiento, posible paso de parámetros innecesarios) o que el Contexto se pase a si mismo como argumento (alto acoplamiento).

Es un patrón que permite mantener un conjunto de algoritmos de los que el objeto cliente puede elegir aquel que le conviene e intercambiarlo según sus necesidades:

  • Varias clases relacionadas que solo difieren en su comportamiento. Estrategia permite configurar a una clase con uno de los comportamientos.
  • Se necesitan variantes de un mismo algoritmo. Se implementan como una jerarquía de clases.
  • Un algoritmo usa datos que un cliente no debe conocer.
  • Una clase define muchos comportamientos basados en condicionales. Mover estas condiciones a la clases de Estrategia.

Fachada

Reducir aun más el acoplamiento haciendo que la Fachada sea una clase abstracta, de forma que se pueda escoger entre diferentes implementaciones del subsistema

El patrón de diseño Fachada sirve para proveer de una interfaz unificada sencilla que haga de intermediaria entre un cliente y una interfaz o grupo de interfaces más complejas.

Es muy recomendable el uso de este patrón si:

  • Se quiere proporcionar una interfaz sencilla para un subsistema complejo.
  • Se quiere desacoplar un subsistema de sus clientes o de otros subsistemas convirtiéndolo en más independiente y portable.
  • Se quiera dividir el sistema por niveles, actuando las fachadas como entradas a cada nivel.

Factoría

Usar plantillas para evitar la herencia

Centraliza en una clase constructora la creación de objetos de un subtipo de un tipo determinado, ocultando al usuario la casuística para elegir el subtipo que crear. Se consideran dos variantes: El caso en que la clase Creador sea abstracta y no provea de una implementación del metodo Factoria o el caso en que la clase Creador sea una clase concreta y provea de una implementación del método Factoría.

Es recomendable el uso de este patrón si:

  • Una clase de objetos no puede prever la clase de objetos que tiene que crear.
  • Las subclases son las que especifiquen los objetos que se crean.
  • Las clases delegan la responsabilidad en una entre varias clases auxilariares

Factoría Abstracta

Crear productos declarando un método factoría por cada Producto

Es un patrón que define una interfaz para crear familias de objetos relacionados o dependientes sin especificar las clases concretas.

Es recomendable el uso del patrón cuando:

  • Un sistema debe de ser independiente de cómo se crean, componen y representan sus productos.
  • Un sistema debe configurarse con una de entre varias familias de productos.
  • Una familia de productos relacionados están hechos para usarse juntos y se necesita cumplir esa restricción.
  • Se desea ofrecer una biblioteca de clases-producto revelando sus interfaces pero no sus implementaciones.

Intérprete

Definir la operación de intérprete usando el patrón Visitante, no hace falta implementarla en cada clase de expresiones

El Intérprete es un patrón de diseño que, dado un lenguaje, define una representación para su gramática junto con un intérprete del lenguaje.

Este patrón es aplicable en los siguientes casos:

  • Cuando tratamos con gramáticas simples, en caso contrario la mejor opción es utilizar parsers.
  • La eficiencia no es uno de los aspectos más importantes. Hay que traducir el input a una forma inmediata.

Iterador

Formalizar un Iterador robusto que permita inserciones y borrados sin alterar el recorrido

Es un patrón define una interfaz que declara los métodos necesarios para acceder secuencialmente a un grupo de objetos de una colección.

El control de la iteración puede realizarse de forma externa, a través del cliente, o realizarlo de forma interna, con el Iterador. En este caso, el Iterador recibe una función a aplicar sobre los elementos del Agregado y el recorrido es automático.

Se recomienda el uso de este patrón:

  • Para acceder a la información de un agregado sin exponer su estructura interna.
  • Se quiere permitir varios tipo de recorrido sobre un agregado.
  • Proporcionar una interfaz uniforme para recorrer diferentes tipos de agregados.

Mediador

Omitir la clase abstracta Mediador

Un Mediador es un patrón de diseño que coordina las relaciones entre sus asociados. Los objetos se comunican con su Mediador cuando se produce un evento. Cada vez que existe un cambio de estado lo notifican al Mediador. El Mediador responde propagando los efectos de dichos eventos a los objetos afectados. No es necesario crear una clase abstracta cuando los objetos solo trabajan con un Mediador. El acoplamiento abstracto de dicha clase permite que los objetos trabajen con diferentes subclases Mediador y viceversa.

Se recomienda el uso del patrón si:

  • Un conjunto grande de objetos se comunica de una forma bien definida, pero compleja.
  • Existe dificulta para reutilizar objetos, ya que nos referimos a varios objetos para comunicarnos.
  • El comportamiento de muchos objetos (que esta distribuido en varias clases) puede resumirse en una o varias por subclasificación.

Memento

Almacenar todos los cambios incrementales de estado en Mementos

El patrón Memento guarda parte o todo el estado interno de un objeto, para que este estado pueda ser restaurado posteriormente.

Este patrón es aplicable en los siguientes casos:

  • Todo o parte del objeto debe de ser almacenado para una posible restauración del mismo.
  • Cuando una interfaz directa para obtener el estado de un objeto exponga detallas de su implementación.

MVC

Separar el desarrollo de una aplicación en tres componentes distintos

Este patrón, o modelo de abstracción, de desarrollo de software separa los datos de una aplicación, la interfaz de usuario y la lógica de negocio en tres componentes distintos. Se ve frecuentemente en aplicaciones web, donde la vista es la página HTML y el código que provee de datos dinámicos a la página. El modelo es el Sistema de Gestión de Base de Datos y la Lógica de negocio, y el controlador es el responsable de recibir los eventos de entrada desde la vista.

Observador

Usar una tabla Hash en el caso de muchos Sujetos y pocos Observadores

 

Este patrón define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, el Observador se encarga de notificar este cambio a resto de los objetos dependientes. Es necesario extender la interfaz de actualización para el Observador sepa qué Sujeto manifestó el cambio.

La actualización mediante la llamada a la notificación se puede realizar de dos maneras: El Sujeto puede hacerlo desde los métodos que cambian de estado, lo que permite desacoplarlo del cliente pero es poco eficiente si hay varios cambios de estados consecutivos. También se puede llamar a la notificación desde el cliente,  delegando en él la responsabilidad de la llamada a notificación

Se recomienda el uso del patrón en los siguientes casos:

  • Cuando una abstracción tiene dos aspectos dependientes el uno del otro. Encapsular los aspectos en objetos distintos permite cambiarlos y reutilizarlos.
  • Cuando cambiar un objeto implica cambiar otros pero no conocemos el número exacto a cambiar.
  • Cuando un objeto debe ser capaz de notificar algo a otros sin hacer suposiciones sobre quienes son dichos objetos. Es decir, cuando se quiere bajo acoplamiento.

Peso Ligero

Dividir el objetivo principal en estados: Estado Intrínseco (elementos que se puedan compartir o son comunes) y Estado Extrínseco (elementos particulares a cada tipo)

Este patrón sirve para eliminar o reducir la redundancia cuando tenemos gran cantidad de objetos que contienen información idéntica.

Se utiliza este patrón si:

  • Se utiliza un gran número de objetos.
  • El coste del almacenamiento es alto debido a la cantidad de objetos.
  • La mayoría de los estados de los objetos pueden ser creados como comunes.
  • Muchos objetos pueden ser reemplazados por unos pocos una vez que han sido borrados los estados comunes.
  • La mayor parte del estado del objeto puede ser extrínseco.

Plantilla

Los métodos abstractos deben ser protegidos (accesible a las subclases pero no a los clientes) y abstractos

Es un patrón de diseño que define una estructura algorítmica en una superclase, delegando la implementación a las subclases.

Se utiliza este patrón para:

  • Factorizar el comportamiento común de varias subclases.
  • Implementar las partes fijas de una algoritmo una sola vez y dejar que las subclases implementen las partes variables.
  • Cuando se diseña una biblioteca. Algunas de las clases pueden tener un comportamiento que dependa de la aplicación que la use. En tal caso, este patrón obliga a que el programador proporcione dicho comportamiento.
  • Definir una estructura lo más reutilizable posible para la autentificación de usuarios.
  • Controlar las ampliaciones de las subclases, convirtiendo en métodos plantillas aquellos métodos que pueden ser redefinidos.

Prototipo

Usar un "Prototipo Manager"

Este patrón tiene como finalidad crear nuevos objetos duplicándolos, clonando una instancia creada previamente. Cuando los prototipos se crean y destruyen constantemente manteniendo un registro de los activos, los clientes no quieren ser los responsables del manejo de los prototipos pero pueden almacenar el registro. Un cliente siempre pregunta al registro antes de clonarlarlo. Este registro de prototipo lo llamamos "Prototipo Manager". El Prototipo Manager es un almacén asociativo que devuelve el prototipo asociado a una clave. De esta manera permitimos al cliente manejar y extender sus prototipos sin necesidad de escribir código.

Se recomienda el uso de este patrón si:

  • Si el sistema debe de ser independiente de cómo, dónde y cuándo se crean sus productos.
  • Permite especificar instancias en tiempos de ejecución.
  • Se quiere reducir el número de clases.
  • Si las instancias que se generan tienen estados limitados.

Proxy

Usarlo para tener un representante de un objeto cuyo acceso resulta complejo

Este patrón nos proporciona un sustituto o representante de otro objeto para controlar el acceso a este.

Este patrón es recomendable en los siguientes casos:

  • Útil cuando se desea retrasar la instanciación de un objeto hasta que sea necesario usarlo.
  • Proporciona un representante local de un objeto situado en otro espacio de direcciones.
  • Uso en sistemas concurrentes mediante cerrojo, controlando el acceso al objeto original.

Puente

Usarlo para desacoplar una clase abstracta de las clases concretas que derivan de ella

La idea de este patrón es desacoplar una abstracción de su implementación, de manera que ambas puedan ser modificadas independientemente sin necesidad de que la alteración de una afecte a la otra.

Se usa el patrón cuando:

  • Se desea evitar un enlace permanente entre la abstracción y su implementación. Esto puede ser debido a que la implementación debe ser seleccionada o cambiada en tiempo de ejecución.
  • Tanto las abstracciones como sus implementaciones deben ser extensibles por medio de subclases. En este caso, el patrón permite combinar abstracciones e implementaciones diferentes y extenderlas independientemente.
  • Cambios en la implementación de una abstracción no deben impactar en los clientes, es decir, su código no debe tener que ser recompilado.
  • Se desea esconder la implementación de una abstracción completamente a los clientes. En C++, la representación de una clase es visible en la interface de la clase.
  • Se desea compartir una implementación entre múltiples objetos (quizá usando contadores) y este hecho debe ser escondido a los clientes.

Singleton

Ocultar el constructor y declarar como estático el método getInstance

El patrón de diseño Singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto. Este patrón es aplicable en sistemas en los que se desea poder garantizar que solo existe una instancia de una clase.

Siempre que se crea un objeto nuevo (en Java, con la palabra reservada new) se invoca al constructor del objeto para que cree una instancia. Por lo general, los constructores son públicos. El Singleton lo que hace es convertir el constructor en privado, de manera que nadie lo pueda instanciar.

Entonces, si el constructor es privado, ¿cómo se instancia el objeto? Pues a través de un método público y estático de la clase. En este método se revisa si el objeto ha sido instanciado antes. Si no ha sido instanciado, llama al constructor y guarda el objeto creado en una variable estática del objeto. Si el objeto ya fue instanciado anteriormente, lo que hace este método es devolver la referencia al estado creado anteriormente.

Visitor

Usar la técnica Double Dispatch para añadir operaciones a las clases

Es un patrón que permite definir nuevas operaciones sobre una jerarquía de clases sin modificar las clases sobre las que opera.

Double Dispatch es una técnica que permite añadir operaciones a las clases sin tener que modificarlas. La operación a ejecutar depende de la clase de petición (acepta) y del tipo de los dos receptores (Visitor, Elemento)

Se recomienda le uso del patrón cuando:

  • Una estructura de objetos contiene muchas clases de objetos con interfaces distintas y se quiere realizar sobre ellos operaciones que son distintas en cada clase concreta.
  • Se quieren realizar muchas operaciones distintas sobre los objetos de una estructura, sin incluir dichas operaciones en las clases.
  • Las clases que forman la estructura de objetos no cambian pero las operaciones sobre ellas sí.

Wizard

Proporcionar comentarios sobre el propósito de cada tarea

Este patrón define un modo de interacción en la presentación de una tarea compleja a un usuario. Este patrón es aplicable cuando el usuario no necesita ser experto para realizar una tarea compleja y poco frecuente basada en varias subtareas que necesitan una toma de decisiones por cada subtarea.

Contenidos relacionados

Recursos
Área: Desarrollo » Patrones de Diseño
Código Título Tipo Carácter
RECU-0013 Patrones de diseño Ficha Recomendado
RECU-0181 Adaptador Patrón Recomendado
RECU-0257 Aplicación del patrón MVC en PHP Referencia Recomendado
RECU-0182 Cadena de Responsabilidades Patrón Recomendado
RECU-0183 Comando Patrón Recomendado
RECU-0184 Composite Patrón Recomendado
RECU-0185 Constructor Patrón Recomendado
RECU-0186 Decorador Patrón Recomendado
RECU-0187 Estado Patrón Recomendado
RECU-0189 Fachada Patrón Recomendado
RECU-0190 Factoría Patrón Recomendado
RECU-0191 Factoría Abstracta Patrón Recomendado
RECU-0192 Intérprete Patrón Recomendado
RECU-0193 Iterador Patrón Recomendado
RECU-0194 Mediador Patrón Recomendado
RECU-0195 Memento Patrón Recomendado
RECU-0196 Observador Patrón Recomendado
RECU-0122 Patrón Modelo Vista Controlador Patrón Recomendado
RECU-0197 Peso Ligero Patrón Recomendado
RECU-0198 Plantilla Patrón Recomendado
RECU-0199 Prototipo Patrón Recomendado
RECU-0200 Proxy Patrón Recomendado
RECU-0201 Puente Patrón Recomendado
RECU-0202 Singleton Patrón Recomendado
RECU-0203 Visitor Patrón Recomendado
RECU-0014 Wizard Ficha Recomendado