Patrones de Diseño

En el presente documento vamos a repasar los patrones de diseño (Design Patterns). Los patrones de diseño nos permiten solucionar diferentes problemas en el desarrollo de software. Para la mayoría de los problemas a los que nos enfrentemos a la hora de diseñar una cierta aplicación, podremos encontrar algún patrón de diseño que nos ayude a plantear de forma adecuada el problema y nos facilite, de esta forma, su solución.

Todo patrón de diseño debe ser reusable y, por lo tanto, aplicable a diferentes problemas de diseño en distintas circunstancias.

A continuación repasaremos los más importantes:

 

Patrones Creacionales

1. Abstract Factory (Fábrica abstracta):

Proporciona una interfaz para crear familias de objetos relacionados o que dependen entre ellos sin especificar sus clases concretas. Por ejemplo, en una fábrica de automóviles un mismo robot puede hacer distintas piezas.

Permite trabajar con objetos de distintas familias de manera que las familias no se mezclen entre sí y haciendo transparente el tipo de familia concreta que se esté usando.

El problema que intenta solucionar este patrón es el de crear diferentes familias de objetos. Uno de los usos más comunes es el de creación de interfaces gráficas de distinto tipo (gtk, qt, etc.), para lo cual se suele combinar con los patrones Singleton y Adapter.

La estructura típica del patrón Abstract Factory es la siguiente:

•La definición de interfaces para la familia de productos genéricos (ej: ventana, menú, botón…)

•Implementación de las interfaces de los productos para cada una de las distintas familias concretas (ej: gtk_ventana, gtk_menú, gtk_botón… y qt_ventana, qt_menú, qt_botón…)

•La definición de los métodos de creación de los productos genéricos en la interfaz de la fábrica (ej: construir_ventana, construir_menú, construir_botón…) cuyo tipo de retorno serán las interfaces genéricas.

•Implementación de una fábrica para cada una de las familias concretas (ej: fábrica_gtk, fábrica_qt).

El patrón Abstract Factory está aconsejado cuando se prevé la inclusión de nuevas familias de productos, pero puede resultar contraproducente cuando se añaden nuevos productos o cambian los existentes. Cuando se usa en conjunción con Singleton se crea una única fábrica, de modo que no habrá usos inconsistentes de los productos en el programa.

 

2. Builder (Constructor virtual):

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.

Abstrae el proceso de creación de un objeto complejo, centralizando dicho proceso en un único punto. El patrón builder(Constructor) es usado para permitir la creación de una variedad de objetos complejos desde un objeto fuente, el objeto fuente se compone de una variedad de partes que contribuyen individualmente a la creación de cada objeto complejo a través de un conjunto de llamadas a interfaces comunes de la clase Abstract Builder.

A menudo, el patrón builder construye el patrón Composite, un patrón estructural.

Intención: Abstrae el proceso de creación de un objeto complejo, centralizando dicho proceso en un único punto, de tal forma que el mismo proceso de construcción pueda crear representaciones diferentes.

 

4. Prototype (Prototipado):

Crea nuevos objetos clonándolos de una instancia ya existente.

Este patrón es motivo donde en ciertos escenarios es preciso abstraer la lógica que decide que tipos de objetos utilizará una aplicación, de la lógica que luego usarán esos objetos en su ejecución. Los motivos de esta separación pueden ser variados, por ejemplo, puede ser que la aplicación deba basarse en alguna configuración o parámetro en tiempo de ejecución para decidir el tipo de objetos que se debe crear.

Este patrón propone la creación de distintas variantes del objeto que nuestra aplicación necesite, en el momento y contexto adecuado. Toda la lógica necesaria para la decisión sobre el tipo de objetos que usará la aplicación en su ejecución debería localizarse aquí. Luego, el código que utiliza estos objetos solicitará una copia del objeto que necesite. En este contexto, una copia significa otra instancia del objeto. El único requisito que debe cumplir este objeto es suministrar la prestación de clonarse. Cada uno de los objetos prototipo debe implementar el método Clone().

 

5. Singleton (Instancia única):

Garantiza la existencia de una única instancia para una clase y la creación de un mecanismo de acceso global a dicha instancia. 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.

Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.

El patrón singleton se implementa creando en nuestra clase un método que crea una instancia del objeto sólo si todavía no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor (con atributos como protegido o privado).

La instrumentación del patrón puede ser delicada en programas con múltiples hilos de ejecución. Si dos hilos de ejecución intentan crear la instancia al mismo tiempo y esta no existe todavía, sólo uno de ellos debe lograr crear el objeto. La solución clásica para este problema es utilizar exclusión mutua en el método de creación de la clase que implementa el patrón.

Las situaciones más habituales de aplicación de este patrón son aquellas en las que dicha clase controla el acceso a un recurso físico único (como puede ser el ratón o un archivo abierto en modo exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos de la aplicación.

El patrón singleton provee una única instancia global gracias a que:

•La propia clase es responsable de crear la única instancia.

•Permite el acceso global a dicha instancia mediante un método de clase.

•Declara el constructor de clase como privado para que no sea instanciable directamente.

 

Patrones Estructurales

6. Adapter (Adaptador):

Adapta una interfaz para que pueda ser utilizada por una clase que de otro modo no podría utilizarla. Adapter se utiliza para transformar una interfaz en otra, de tal modo que una clase que no pudiera utilizar la primera, haga uso de ella a través de la segunda.

Se tiene un componente con cierta funcionalidad que se desea aprovechar, pero este componente no cumple determinada interfaz, siendo esto último imperativo.

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.

La diferencia entre los patrones Adapter y Facade, es que el primero reutiliza una interfaz ya existente, mientras que el segundo define una nueva.

 

7. Bridge (Puente):

Desacopla una abstracción de su implementación.

Bridge sirve para desacoplar una abstracción de su implementación, de manera que ambas puedan ser modificadas independientemente sin necesidad de alterar por ello la otra.

Problema que soluciona

Para obtener una implementación alternativa, se ha creado una clase Implementación que hereda de otra clase Abstracción base.

Problema: Ahora no se puede modificar la clase Abstracción sin afectar a la clase hija. Tampoco podemos modificar la clase hija sin que el comportamiento de la clase Abstracción padre varíe, ya que delega funcionalidad en la hija.

Implementación

Creamos una clase Abstracción padre que sea abstracta, además de abstracciones concretas mediante clases que heredan de ella. Por otro lado se tienen las clases que implementan la funcionalidad con una estructura similar: una clase ImplementaciónAbstracta padre, y todas las clases hijas necesarias que implementan la funcionalidad de todas las maneras necesarias. La relación se da entra la clase abstracta Abstracción y la clase abstracta Implementación, delegando la primera la implementación en la segunda, que a su vez la delega en las implementaciones concretas.

 

8. Composite (Objeto compuesto):

Permite tratar objetos compuestos como si de uno simple se tratase.

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.

Esto simplifica el tratamiento de los objetos creados, ya que al poseer todos ellos una interfaz común, se tratan todos de la misma manera.

Problema que soluciona

Necesitamos crear una serie de clases para guardar información acerca de una serie de figuras que serán círculos, cuadrados y triángulos. Además necesitamos poder tratar también grupos de imágenes porque nuestro programa permite seleccionar varias de estas figuras a la vez para moverlas por la pantalla.

En principio tenemos las clases Círculo, Cuadrado y Triangulo, que heredarán de una clase padre que podríamos llamar Figura e implementarán todas la operación pintar(). En cuanto a los grupos de Figuras podríamos caer en la tentación de crear una clase particular separada de las anteriores llamada GrupoDeImagenes, también con un método pintar().

Problema.

Esta idea de separar en clases particulares componentes (figuras) y contenedores (grupos) tiene el problema de que, para cada uno de los dos tipos, el método pintar() tendrá una implementación diferente, aumentando la complejidad del sistema.

 

9. Decorator (Envoltorio):

Añade funcionalidad a una clase dinámicamente.

Decorator responde a la necesidad de añadir dinámicamente funcionalidad a una clase existente. Esto nos permite no tener que crear sucesivas clases que hereden de la primera incorporando la nueva funcionalidad, sino otras que la implementan y se asocian a la primera.

Problema que soluciona

Supongamos que tenemos una clase existente Ventana y queremos añadirle funcionalidad para que muestre un borde alrededor. Podemos crear una subclase VentanaConBorde que herede de Ventana.

Hasta aquí todo bien, pero supongamos que surge la necesidad de crear una ventana que muestre un pequeño botón de ayuda con un signo de interrogación (?) en su parte superior. Entonces tenemos las siguientes opciones:

•Crear otra subclase de Ventana: VentanaConBotónDeAyuda.

Problema: No cubre la necesidad de tener ventanas con bordes y botón de ayuda a la vez.

•Crear una subclase de VentanaConBorde: VentanaConBordeYBotonDeAyuda.

Problema: No tenemos una ventana con botón de ayuda y sin borde.

•Crear clases para todas las combinaciones posibles de funcionalidades.

Problema: Con este ejemplo tendríamos cuatro clases: Ventana, VentanaConBorde, VentanaConBotonDeAyuda y VentanaConBordeYBotonDeAyuda; con tres funcionalidades tendríamos siete clases y con cuatro, ¡quince!

El patrón Decorator soluciona este problema de una manera mucho más sencilla y extensible.

Se crea a partir de Ventana la subclase abstracta VentanaDecorator y, heredando de ella, BordeDecorator y BotonDeAyudaDecorator. VentanaDecorator encapsula el comportamiento de Ventana y utiliza composición recursiva para que sea posible añadir tantas “capas” de Decorators como se desee. Podemos crear tantos Decorators como queramos heredando de VentanaDecorator.

 

10. Facade (Fachada):

Provee de una interfaz unificada simple para acceder a una interfaz o grupo de interfaces de un subsistema.

El patrón Facade 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.

Problema: Un cliente necesita acceder a parte de la funcionalidad de un sistema más complejo.

•Definir una interfaz que permita acceder solamente a esa funcionalidad.

Problema: Existen grupos de tareas muy frecuentes para las que se puede crear código más sencillo y legible.

•Definir funcionalidad que agrupe estas tareas en funciones o métodos sencillos y claros.

Problema: Una biblioteca es difícilmente legible.

•Crear un intermediario más legible.

Problema: Dependencia entre el código del cliente y la parte interna de una biblioteca.

•Crear un intermediario y realizar llamadas a la biblioteca solo o, sobre todo, a través de él.

Problema: Necesidad de acceder a un conjunto de APIs, que pueden además tener un diseño no muy bueno.

•Crear una API intermedia, bien diseñada, que permita acceder a la funcionalidad de las demás.

Cuidado: Facade debe utilizarse para crear clases sencillas, no clases que “sirvan para todo” o “lo hagan todo”.-****

Facade provee una única y sencilla interfaz para la gran mayoría de los clientes que realizan peticiones simples. Facade no oculta los objetos del subsistema, por lo que aquellos clientes que requieren mayor personalización pueden realizar las peticiones por encima de Facade. Facade provee una solución para el diseño de software en capas. Facade provee un alto grado de desacoplamiento.

 

11. Flyweight (Peso ligero):

Reduce la redundancia cuando gran cantidad de objetos poseen idéntica información.

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

Problema que soluciona

Necesitamos representar gráficamente muchas pelotas idénticas que rebotan en los bordes de una ventana, así que creamos una clase que tenga por atributos las coordenadas, el radio y el color con que se dibujará la pelota.

Problema: Aunque las coordenadas son distintas, como queremos que nuestras pelotas sean iguales, el radio y el color se repetirán en cada instancia, desperdiciando memoria.

Implementación

Crear una clase PelotaFlyweight, que contendrá la información común (radio y color) y otra clase PelotaConcreta, que contendrá las coordenadas concretas de cada pelota y una referencia a un objeto de tipo PelotaFlyweight.

Al crearse instancias de PelotaConcreta, se les deberá proveer de referencias a la instancia de PelotaFlyweight adecuada a nuestras necesidades.

En este caso solamente tendríamos una instancia de PelotaFlyweight, puesto que hemos dicho que todas nuestras pelotas tienen el mismo radio y color, pero pensando en un ejemplo en el que tuviéramos varios grupos de pelotas, y dentro de cada uno de los cuales se compartieran el radio y el color, se puede utilizar Flyweight conjuntamente con el patrón Factory, de tal modo que este último, en el momento en que se le soliciten instancias de PelotaConcreta con determinadas características (mismo radio y color que el solicitado), compruebe si ya existe un PelotaFlyweight con ese radio y color, y devuelva esa referencia o, en caso de que no exista, la cree y la registre. El patrón Factory se encargaría de gestionar los PelotaFlyweight existentes.

 

12. Proxy:

Mantiene un representante de un objeto.

Proxy se utiliza como intermediario para acceder a un objeto, permitiendo controlar el acceso a él.

Problema que soluciona

Necesitamos crear objetos que consumen muchos recursos, pero no queremos instanciarlos a no ser que el cliente lo solicite o se cumplan otras condiciones determinadas.

Implementación

Tenemos un objeto padre Asunto del que heredan otros dos: AsuntoReal y Proxy, todos ellos tienen un método petición(). El cliente llamaría al método petición() de Asunto, el cual pasaría la petición a Proxy, que a su vez instanciaría AsuntoReal y llamaría a su petición().

Esto nos permite controlar las peticiones a AsuntoReal mediante el Proxy, por ejemplo instanciando AsuntoReal cuando sea necesario y eliminándolo cuando deje de serlo.

 

Patrones de Comportamiento

 13. Chain of Responsibility (Cadena de responsabilidad):

Permite establecer la línea que deben llevar los mensajes para que los objetos realicen la tarea indicada.

Se utiliza, por ejemplo, cuando en función del estado del sistema las peticiones emitidas por un objeto deben ser atendidas por distintos objetos receptores.

Implementación

Todos los objetos receptores implementarán la misma interfaz o extenderán la misma clase abstracta. En ambos casos se proveerá de un método que permita obtener el sucesor y así el paso de la petición por la cadena será lo más flexible y transparente posible.

 

14. Command (Orden):

Encapsula una operación en un objeto, permitiendo ejecutar dicha operación sin necesidad de conocer el contenido de la misma.

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. Para ello se encapsula la petición como un objeto, con lo que además se facilita la parametrización de los métodos.

Propósito

•Encapsula un mensaje como un objeto, con lo que permite gestionar colas o registro de mensaje y deshacer operaciones.

•Soportar restaurar el estado a partir de un momento dado.

•Ofrecer una interfaz común que permita invocar las acciones de forma uniforme y extender el sistema con nuevas acciones de forma más sencilla.

Motivo

•El concepto de “orden” puede ser ambiguo y complejo en los sistemas actuales y al mismo tiempo muy extendido: intérpretes de órdenes del sistema operativo, lenguajes de macros de paquetes ofimáticos, gestores de bases de datos, protocolos de servidores de Internet, etc.

•Este patrón presenta una forma sencilla y versátil de implementar un sistema basado en comandos facilitándose su uso y ampliación.

Aplicaciones

•Facilitar la parametrización de las acciones a realizar.

•Independizar el momento de petición del de ejecución.

•Implementar CallBacks, especificando que órdenes queremos que se ejecuten en ciertas situaciones de otras órdenes. Es decir, un parámetro de una orden puede ser otra orden a ejecutar.

•Soportar el “deshacer”.

•Desarrollar sistemas utilizando órdenes de alto nivel que se construyen con operaciones sencillas (primitivas).

 

15. Interpreter (Intérprete):

Dado un lenguaje, define una gramática para dicho lenguaje, así como las herramientas necesarias para interpretarlo.

Propósito Dado un lenguaje, define una representación para su gramática junto con un intérprete del lenguaje

Usos Conocidos Definir un lenguaje para representar expresiones regulares que representen cadenas a buscar dentro de otras cadenas En general, definir un lenguaje que permita representar las distintas instancias de una familia de problemas

 

16. Iterator (Iterador):

Permite realizar recorridos sobre objetos compuestos independientemente de la implementación de estos.

En diseño de software, el patrón de diseño Iterador, define una interfaz que declara los métodos necesarios para acceder secuencialmente a una colección de objetos. Algunos de los métodos que podemos definir en la Interfase Iterator son:

Primero(), Siguiente(), haymas() y elementoactual()

Con el uso de este patrón, no es necesario conocer la estructura interna de la colección para poder utilizarla.

 

17. Mediator (Mediador):

Define un objeto que coordine la comunicación entre objetos de distintas clases, pero que funcionan como un conjunto.

Un Mediator (o patrón de diseño) coordina las relaciones entre sus asociados. Permite la interacción de varios objetos, sin generar acoples fuertes en esas relaciones.

Motivación

Cuando muchos objetos interactúan con otros objetos, se puede formar una estructura muy compleja, con objetos con muchas conexiones con otros objetos. En un caso extremo cada objeto puede conocer a todos los demás objetos. Para evitar esto el patrón Mediator encapsula el comportamiento de todo un conjunto de objetos en un solo objeto.

Aplicabilidad

Usar el patrón Mediator cuando:

•Un conjunto grande de objetos se comunica de una forma bien definida, pero compleja.

•Rehusar un objeto se hace difícil por que se relaciona con muchos objetos.

•El comportamiento de muchos objetos que esta distribuido entre varias clases, puede resumirse en una o varias por subclasificacion.

 

18. Memento (Recuerdo):

Permite volver a estados anteriores del sistema.

El patrón de diseño Memento, tiene como finalidad almacenar el estado de un objeto (o del sistema completo) en un momento dado de manera que se pueda restaurar en ese punto de manera sencilla. Para ello se mantiene almacenado el estado del objeto para un instante de tiempo en una clase independiente de aquella a la que pertenece el objeto (pero sin romper la encapsulación), de forma que ese recuerdo permita que el objeto sea modificado y pueda volver a su estado anterior.

Motivación

Se usa este patrón cuando se quiere poder restaurar el sistema desde estados pasados y por otra parte, es usado cuando se desea facilitar el hacer y deshacer de determinadas operaciones, para lo que habrá que guardar los estados anteriores de los objetos sobre los que se opere (o bien recordar los cambios de forma incremental).

 

19. Observer (Observador):

Define una dependencia de uno-a-muchos entre objetos, de forma que cuando un objeto cambie de estado se notifique y actualicen automáticamente todos los objetos que dependen de él.

El patrón Observador define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, el observador de encarga de notificar este cambio a todos los otros dependientes.

Este patrón también se conoce como el patrón de publicación-suscripción o modelo-vista. Estos nombres sugieren las ideas básicas del patrón, que son bien sencillas: el objeto de datos, llamémoslo “Sujeto” a partir de ahora, contiene métodos mediante los cuales cualquier objeto observador o vista se puede suscribir a él pasándole una referencia a si mismo. El Sujeto mantiene así una lista de las referencias a sus observadores.

Los observadores a su vez están obligados a implementar unos métodos determinados mediante los cuales el Sujeto es capaz de notificar a sus observadores “suscritos” los cambios que sufre para que todos ellos tengan la oportunidad de refrescar el contenido representado. De manera que cuando se produce un cambio en el Sujeto, ejecutado, por ejemplo, por alguno de los observadores, el objeto de datos puede recorrer la lista de observadores avisando a cada uno.

 

20. State (Estado):

Permite que un objeto modifique su comportamiento cada vez que cambie su estado interno.

El patrón de diseño State se utiliza cuando el comportamiento de un objeto cambia dependiendo del estado del mismo. Por ejemplo: una alarma puede tener diferentes estados, como desactivada, activada, en configuración. Definimos una interface Estado_Alarma, y luego definimos los diferentes estados.

Propósito

Permite a un objeto alterar su comportamiento según el estado interno en que se encuentre.

Motivación

El patrón State está motivado por aquellas clases que, según su estado actual varía su comportamiento ante los diferentes mensajes. Como ejemplo se toma una clase TCPConection la que representa una conexión de red, un objeto de esta clase tendrá diferentes respuestas según su estado (Listening, Close o Established). Por ejemplo una llamada al método Open de un objeto de la clase TCPConection diferirá su comportamiento si la conexión se encuentra en Close o en Established.

Solución

Se implementa una clase para cada estado diferente del objeto y el desarrollo de cada método según un estado determinado. El objeto de la clase a la que le pertenecen dichos estados resuelve los distintos comportamientos según su estado, con instancias de dichas clases de estado. Así, siempre tiene presente en un objeto el estado actual y se comunica con este para resolver sus responsabilidades.

La idea principal en el patrón State es introducir una clase abstracta TCPState que representa los estados de la conexión de red y una interfaz para todas las clases que representan los estados propiamente dichos. Por ejemplo la clase TCPEstablished y la TCPClose implementan responsabilidades particulares para los estados establecido y cerrado respectivamente del objeto TCPConection. La clase TCPConection mantiene una instancia de alguna subclase de TCPState con el atributo state representando el estado actual de la conexión. En la implementación de los métodos de TCPConection habrá llamados a estos objetos representados por el atributo state para la ejecución de las responsabilidades, así según el estado en que se encuentre, enviará estos llamados a un objeto u otro de las subclases de TCPState.

 

21. Strategy (Estrategia):

Permite disponer de varios métodos para resolver un problema y elegir cuál utilizar en tiempo de ejecución.

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

Los distintos algoritmos se encapsulan y el cliente trabaja contra un objeto contexto o Context. Como hemos dicho, el cliente puede elegir el algoritmo que prefiera de entre los disponibles o puede ser el mismo objeto Context el que elija el más apropiado para cada situación.

Cualquier programa que ofrezca un servicio o función determinada, que pueda ser realizada de varias maneras, es candidato a utilizar el patrón Strategy. Puede haber cualquier número de estrategias y cualquiera de ellas podrá ser intercambiada por otra en cualquier momento, incluso en tiempo de ejecución.

 

22. Template Method (Método plantilla):

Define en una operación el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos, esto permite que las subclases redefinan ciertos pasos de un algoritmo sin cambiar su estructura.

Un Template Method es un patrón de diseño el cual define una estructura algorítmica en la súper clase, delegando la implementación a las subclases. Es decir, define una serie de pasos, en donde los pasos serán redefinidos en las subclases.

Propósito

Usando el Template Method, se define una estructura de herencia en la cual la superclase sirve de plantilla (“Template” significa plantilla) de los métodos en las subclases. Una de las ventajas de este método es que evita la repetición de código, por tanto la aparición de errores.

¿Cuándo Usarlo?

Este patrón se vuelve de especial utilidad cuando es necesario realizar un algoritmo que sea común para muchas clases, pero con pequeñas variaciones entre una y otras.

 

23. Visitor (Visitante):

Este patrón sirve para indicar que alguien (visitador) visitó a otra cosa, y así saber que eso ha sido visitado, por un visitador

En programación orientada a objetos, el patrón visitor es una forma de separar el algoritmo de la estructura de un objeto.

La idea básica es que se tiene un conjunto de clases que forman la estructura de un objeto. Cada una de estas clases elemento, tiene un método aceptar que recibe al objeto visitador como argumento. El visitor es una interfaz que tiene un método visitor diferente para cada clase elemento, esto es visitorClase1, visitorClase2… visitorClaseN. El método aceptar de una clase elemento llama al método visit de su clase. Clases concretas de visitor pueden entonces ser escritas para hacer una operación en particular.

Uno de los métodos visit de un visitor concreto puede ser pensado como métodos que no son de una sola clase, sino métodos de un par de clases: el visitor concreto y clase elemento particular. Así el patrón visitor simula el envío doble (en inglés éste término se conoce como Double-Dispatch) en un lenguaje convencional orientado a objetos de envío único (Como Java o C++).

El patrón visitor también especifica cómo sucede la interacción en la estructura del objeto. En su versión más sencilla, donde cada algoritmo necesita iterar de la misma forma, el método aceptar de un elemento contenedor, además de una llamada al método visitor, también pasa el objeto visitor al método accept de todos sus elementos hijos.

Este patrón es ampliamente utilizado en intérpretes, compiladores y procesadores de lenguajes, en general.

About these ads

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

A %d blogueros les gusta esto: