Unidad Docente de Ingeniería del Software. Facultad de informática - Universidad Politécnica de Madrid



Documentos relacionados
Centro de Capacitación en Informática

Para ingresar a la aplicación Microsoft PowerPoint 97, los pasos que se deben seguir pueden ser los siguientes:

Patrones de Diseño Orientados a Objetos 2 Parte

UTILIZACIÓN DE UNA CUENTA DE CORREO ELECTRÓNICO (NUEVO) Acceso al correo electrónico

GUIA PROGRAMACIÓN ORIENTADA A OBJETOS

Introducción a Visual Studio.Net

Caso práctico de Cuadro de Mando con Tablas Dinámicas

Para crear formularios se utiliza la barra de herramientas Formulario, que se activa a través del comando Ver barra de herramientas.

Microsoft Excel Unidad 6. La Hoja de Cálculo

INTRODUCCIÓN A LOS SISTEMAS GESTORES DE BASE DE DATOS

InfoPath forma parte del paquete ofimático de Microsoft desde la versión XP (2003).

La ventana de Microsoft Excel

Correspondencias entre taxonomías XBRL y ontologías en OWL Unai Aguilera, Joseba Abaitua Universidad de Deusto, EmergiaTech

Patrones Creacionales Builder. Patrones Creacionales Abstract Factory. Patrones Creacionales Singleton. Patrones Creacionales Prototype

LABORATORIO Nº 2 GUÍA PARA REALIZAR FORMULAS EN EXCEL

Tutorial de UML. Introducción: Objetivos: Audiencia: Contenidos:

Elementos de Microsoft Word

5.1. Organizar los roles

Es una aplicación basada en sistemas con pantallas táctiles, lo cual permite un rápido aprendizaje y una gran facilidad de manejo.

Manual para Empresas Prácticas Curriculares

Programa Presupuestos de Sevillana de Informática.

INSTRUCCIÓN DE SERVICIO NOCIONES BÁSICAS PARA DIAGRAMAS DE FLUJO. MICROSOFT VISIO

EDICIÓN Y FORMATO (II)

2. Conceptos básicos Abstracción La abstracción como un proceso mental natural La abstracción en el desarrollo de software

Manual de ayuda para crear y gestionar Tareas, como actividad evaluable

Introducción. Ciclo de vida de los Sistemas de Información. Diseño Conceptual

UF0320: Aplicaciones informáticas de tratamiento de textos

Capítulo 4 Patrones y Patrones de Diseño (ii)

SISTEMA DE GESTIÓN DE BASE DE DATOS (Database Management System (DBMS))

Manual Impress Impress Impress Impress Impress Draw Impress Impress

MACROS Y FORMULARIOS

Diagramas del UML. A continuación se describirán los diagramas más comunes del UML y los conceptos que representan: Diagrama de Clases

MANUAL DEL PROGRAMA DE ASESORAMIENTO (Asesores) Navegador y limpiar caché/cookies...2 Acceso al programa de Asesoramiento... 7

GUÍA RÁPIDA DE TRABAJOS CON ARCHIVOS.

Manual de usuario para Android de la aplicación PORTAFIRMAS MÓVIL

Una base de datos es una colección de información ordenada e interrelacionada que es de importancia para una empresa.

1 La Resolución de Problemas utilizando la Computadora

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

Instructivo para la elaboración de un Manual Técnico

Capítulo 11. Conclusiones y trabajo futuro

Colección de Tesis Digitales Universidad de las Américas Puebla. Morales Salcedo, Raúl

Manual de OpenOffice Impress

PATRONES DE DISEÑO. FAVA - Formación en Ambientes Virtuales de Aprendizaje. SENA - Servicio Nacional de Aprendizaje

CAPÍTULO I. Sistemas de Control Distribuido (SCD).

Criterios para seleccionar tecnología de Modelos de Toma de Decisiones

11/06/2011. Alumno: José Antonio García Andreu Tutor: Jairo Sarrias Guzman

CASO PRÁCTICO DISTRIBUCIÓN DE COSTES

Sistemas de Operación II

Curso Internet Básico - Aularagon

Tutorial de Introducción a la Informática Tema 0 Windows. Windows. 1. Objetivos

Instructivo Asesoría Básica Comunidad Virtual SharePoint 2010

Los requisitos de accesibilidad en un proyecto software. Implicaciones de usuarios discapacitados en el proceso software

Manual del Profesor Campus Virtual UNIVO

TEMA 5: HOJAS DE CÁLCULO. Edición de hojas de cálculo con OpenOffice Calc

VAST: Manual de usuario. Autores: Francisco J. Almeida-Martínez Jaime Urquiza-Fuentes

SISTEMAS OPERATIVOS AVANZADOS

Google Drive. Registro y gestión de archivos. Manual de uso

En esta unidad añadiremos información sobre EXT3 y trabajaremos con aspectos visibles que nos proporcionan estos sistemas de archivos.

ORDEN ORGANIZACIÓN ESTANDARIZACIÓN LIMPIEZA INTEGRACIÓN

1. La nueva interfaz del programa

Aplicación de la metodología de las 5 S al diseño de tarjetas de

TALLER No. 1 Capitulo 1: Conceptos Básicos de Bases de datos

2.2.- Paradigmas de la POO

UML, ejemplo sencillo sobre Modelado de un Proyecto

GUÍA TÉCNICA PARA LA DEFINICIÓN DE COMPROMISOS DE CALIDAD Y SUS INDICADORES

PROGRAMACIÓN ORIENTADA A OBJETOS

Operación Microsoft Access 97

El muestreo archivístico, que es una de las técnicas de la Valoración Documental, ha sido

Proyectos de Innovación Docente

Repetir el proceso para cada abstracción identificada hasta que el diseño este expresado en términos sencillos

Capitulo V Administración de memoria

Introducción al diseño híbrido con ZW3D

Módulo II - PowerPoint

Desarrollo de un Sistema de Gestión de Proyectos mediante el framework GWT

Combinar comentarios y cambios de varios documentos en un documento

El reto de la Gestión Documental

Unidad II: Diseño de Bases de Datos y el modelo E-R. 2.1 El Proceso de Diseño

Análisis de esquemas XML [1]

NOTIFICACIÓN DE MOVIMIENTOS DE ESTUPEFACIENTES POR PARTE DE LOS LABORATORIOS FARMACÉUTICOS Y ALMACENES MAYORISTAS DE DISTRIBUCIÓN

TEMA 7: DIAGRAMAS EN UML

NOVEDADES Y MEJORAS. datahotel versión 9.00 TRABAJAR CON I.V.A INCLUIDO

Impress : Programa de presentaciones de OpenOffice.

Módulo 8: Ofimática básica. Unidad didáctica 4: Como obtener ayuda en Word. Procesador de textos: Word

IAP ENTORNOS INFORMATIZADOS CON SISTEMAS DE BASES DE DATOS

Curso de Doctorado: Tecnologías de Objetos

Comercial Cartas de Fidelización

WinHIPE: edición, compilación y ejecución de programas; y generación de animaciones web. Manual de usuario.

QUÉ ES Y PARA QUÉ SIRVE UML? VERSIONES DEL LENGUAJE UNIFICADO DE MODELADO. TIPOS DE DIAGRAMAS. INGENIERÍA DEL SOFTWARE (DV00205D)

Entidad Formadora: Plan Local De Formación Convocatoria 2010

ÍNDICE 2. DIRECCIONES DE INTERÉS SOBRE TELETRABAJO Y DISCAPACIDAD BIBLIOGRAFÍA...

Dando nuestros primeros pasos con 3DS Max. 1. Objetivos

Vamos a ver las dos formas básicas de arrancar PowerPoint.

SEGUIMIENTO EDUCATIVO. Comunicaciones

Software Reutilizable. Ian Sommerville 2004 Software Engineering, 7th edition. Chapter 18 Slide 1

TABLA DE DECISION. Consideremos la siguiente tabla, expresada en forma genérica, como ejemplo y establezcamos la manera en que debe leerse.

SISTEMA DE APARTADO DE SALAS PARA EVENTOS

Planificación, Administración n de Bases de Datos. Bases de Datos. Ciclo de Vida de los Sistemas de Información. Crisis del Software.

MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO

Evaluación del desempeño: los miembros de la familia, a examen

Este botón situado en la barra de título de la ventana de la aplicación, nos da acceso a un menú mediante el cual podemos, entre otras opciones:

Transcripción:

Unidad Docente de Ingeniería del Software Facultad de informática - Universidad Politécnica de Madrid

Índice ACCIÓN / COMMAND...1 ADAPTADOR / ADAPTER...6 APODERADO / PROXY...7 CADENA DE RESPONSABILIDADES / CHAIN OF RESPONSIBILITY...11 COMPOSICIÓN / COMPOSITE...14 CONSTRUCTOR / BUILDER...15 DECORADOR / DECORATOR...19 ESTADO / STATE...21 ESTRATEGIA / STRATEGY...22 FÁBRICA ABSTRACTA / ABSTRACT FACTORY...25 FACHADA / FACADE...26 INTÉRPRETE / INTERPRETER...28 ITERADOR / ITERATOR...32 MEDIADOR / MEDIATOR...34 MÉTODO DE FÁBRICA / FACTORY METHOD...35 MÉTODO PLANTILLA / TEMPLATE METHOD...37 OBSERVADOR / OBSERVER...41 PESO MOSCA / FLYWEIGHT...42 PROTOTIPO / PROTOTYPE...44 PUENTE / BRIDGE...46 RECUERDO / MEMENTO...48 - i -

SOLITARIO / SINGLETON...50 VISITANTE / VISITOR...53 - ii -

ACCIÓN / COMMAND Tipo Comportamiento, a nivel de objetos. Problema Uno de los elementos principales de una interfaz gráfica de usuario (GUI) son los menús desplegables. En el interior de un menú se encuentran una serie de operaciones, funciones o facilidades que una aplicación ofrece con relación a un tema en concreto (Archivo, Edición, Ver, Insertar, Formato, etc...). Las distintas entradas de un menú tienen la característica de que al ser pinchadas con el ratón o al ser seleccionadas mediante teclado ejecutan una operación concreta. Un modelo de objetos que represente lo anterior puede ser el siguiente: APLICACIÓ N Añadir(doc) MENÚ Añadir(entr) ENTRADA Seleccionar() aplicación doc ENTRADA_ABRIR PedirNombre() Seleccionar() DOCUMENTO Abrir() Cerrar() Copiar() nb=pedirnombre(); doc=new Documento(nb); aplicación->añadir(doc); doc->abrir(); El siguiente escenario muestra como interactúan los objetos del modelo anterior: doc:documento m:menú e_a:entrada_abrir ap:aplicación new Entrada_Abrir(e_a) Añadir(e_a) new Documento(doc) Abrir() Seleccionar() Añadir(doc) - 1 -

Otro elemento relevante de una GUI hoy en día son las barras de botones, al igual que, en los comienzos de estas interfaces, también lo fueron, con una misión similar, las combinaciones de teclas. En la mayoría de los casos, un botón sirve para ejecutar alguna de las funciones más usuales de la aplicación, por lo cual coincide, en la función que desempeña, con alguna entrada de algún menú. Al modelo de objetos anterior se le han añadido en negrita las novedades necesarias para representar las barras de botones: BARRA APLICACIÓ N Añadir(doc) MENÚ Añadir(entr) ENTRADA Seleccionar() Añadir(bot) BOTÓN Presionar() ENTRADA_ABRIR aplicación doc PedirNombre() Seleccionar() doc BOTÓN_ABRIR PedirNombre() Presionar() DOCUMENTO Abrir() Cerrar() Copiar() nb=pedirnombre(); doc=new Documento(nb); aplicación->añadir(doc); doc->abrir(); aplicación nb=pedirnombre(); doc=new Documento(nb); aplicación->añadir(doc); doc->abrir(); Para el caso de los botones el escenario es similar: doc:documento b:barra b_a:botón_abrir ap:aplicación new Botón_Abrir(b_a) Añadir(b_a) new Documento(doc) Abrir() Presionar() Añadir(doc) El problema de esta solución es que se duplica la implementación de la operación que ejecutan tanto la entrada de menú como el botón. El hecho de que existan dos o más alternativas para acceder a una misma función de la aplicación (algo positivo, en principio) no debe traducirse en redundancia a la hora de implantar dicha función (algo negativo, por el desperdicio de recursos que ello implica). - 2 -

Una solución que nos permite evitar esa redundancia consiste en definir la acción que se quiere ejecutar como un objeto, al cual pueden referirse todos aquellos elementos gráficos que lo deseen. Aplicando esta idea tenemos la siguiente estructura: APLICACIÓ N Añadir(doc) MENÚ Añadir(entr) ENTRADA AsignarAcc() Seleccionar() acción acción ACCIÓN BARRA Añadir(bot) Ejecutar() acción->ejecutar() DOCUMENTO Abrir() Cerrar() Copiar() aplicación doc nb=pedirnombre(); doc=new Documento(nb); aplicación->añadir(doc); doc->abrir(); ABRIR PedirNombre() Ejecutar() acción->ejecutar() BOTÓN AsignarAcc() Presionar() Los escenarios siguientes representan, respectivamente, la creación y posterior asignación de una nueva acción a una entrada de menú y un botón, así como la ejecución de dicha acción mediante la selección de ambos elementos gráficos: bot:botón ent:entrada acción:abrir ap:aplicación new Abrir(acción) AsignarAcc(acción) AsignarAcc(acción) doc:documento Seleccionar() ent:entrada acción:abrir ap:aplicación Ejecutar() new Documento(doc) Añadir(doc) Abrir() doc:documento bot:botón acción:abrir ap:aplicación Presionar() Ejecutar() new Documento(doc) Abrir() Añadir(doc) Solución - 3 -

Encapsular en un objeto la acción que satisface una petición. Contexto La solución anterior es apropiada cuando lo fundamental en la relación entre una petición y la acción que la satisface es la FLEXIBILIDAD. Este patrón, al encapsular en un objeto la acción, promueve una separación entre dicha acción y la petición que resuelve, lo cual redunda en una mayor flexibilidad en todo lo relativo a la acción. Esto tiene las siguientes consecuencias: Diferentes objetos pueden ejecutar la misma acción sin necesidad de repetir su declaración e implementación. Basta con que la compartan 1. Se puede cambiar con facilidad (incluso dinámicamente) la acción que realiza o está asociada a un objeto. Se pueden añadir nuevas acciones sin tocar las clases ya existentes 2. Se puede especificar, encolar y ejecutar una acción en momentos diferentes 3. Se puede contemplar la posibilidad de deshacer una operación. Para ello es necesario disponer de una lista de históricos en la que se reflejen los diferentes estados por los que pasa el sistema o el objeto afectado por las sucesivas operaciones. Igual que se deshacen una o varias operaciones, se puede dar la posibilidad de volver a hacer ( rehacer ) operaciones ya deshechas. Se pueden ensamblar acciones, para formar una acción compuesta (macroacción). Esto puede resultar interesante en sistemas de información que dan soporte a transacciones 4. Estructura PETICIONARIO AsignarAcción() AtenderPetición() acción acción->ejecutar() ACCIÓN Ejecutar() RECEPTOR Operación() receptor ACCIÓN CONCRETA CLIENTE receptor -> Operación() Ejecutar() Relacionado con Composición puede usarse para implementar macroacciones, es decir, Acciones compuestas. estado 1 No se trata de compartir un objeto concreto, sino una clase, a través de instancias distintas de la misma. 2 Al representar las acciones como objetos de pleno derecho se da la posibilidad de modificarlas y/o extenderlas, como al resto de los objetos, aplicando los mecanismos que para ello ofrece la teoría de objetos. 3 Como se ha separado la petición de la acción que la satisface, es posible que tengan un tiempo de vida distinto, es decir, unas historias no necesariamente paralelas. 4 Una transacción encapsula una serie de cambios efectuados sobre unos datos. Este patrón sirve muy bien a este interés, porque permite estructurar el sistema en base a acciones de alto nivel, que se constituyen a partir de operaciones primitivas. - 4 -

Recuerdo puede usarse para guardar el estado del sistema antes de que una petición sea atendida y así poder luego deshacer el efecto de la Acción ejecutada. Una Acción de la que necesariamente debe hacerse copia antes de ser introducida en la lista de históricos se comporta como un Prototipo. Otros aspectos de interés El Cliente es el responsable de crear la AcciónConcreta correspondiente a una petición y de configurarla con el Receptor que sabe resolverla. Acción suele ser una clase abstracta que define la interfaz para la ejecución de operaciones. Para dar soporte a operaciones que se puedan deshacer y/o rehacer es preciso almacenar la información de estado que permita hacerlo y si además se pretende hacer esto en múltiples niveles habrá que mantener una lista de históricos con las acciones ya ejecutadas. Cada AcciónConcreta establece una relación entre el receptor de la petición y la acción que éste realiza para satisfacerla. Para permitir deshacer y/o rehacer operaciones, el estado debe contener información relativa a los receptores, las acciones y las operaciones involucradas en el proceso. Las habilidades de cada AcciónConcreta van desde la simple invocación de la correspondiente Operación del Receptor hasta la implementación interna de toda la acción que satisface la petición. - 5 -

ADAPTADOR / ADAPTER Tipo Estructura, tanto a nivel de clases como a nivel de objetos. Propósito Convertir la interfaz de una clase para que se adapte a lo que el cliente que la usa necesita, permitiendo así que trabajen juntas clases cuyas interfaces son incompatibles. Estructura A nivel de clases... CLIENTE OBJETIVO Petición() CLASE A ADAPTAR PeticiónConcreta() ADAPTADOR PeticiónConcreta() Petición() A nivel de objetos... CLIENTE OBJETIVO Petición() CLASE A ADAPTAR PeticiónConcreta() ADAPTADOR Petición() adaptado adaptado->peticiónconcreta() Cuando usarlo Cuando se quiere usar una clase ya existente, pero su interfaz no encaja con lo que se necesita. Cuando se quiere crear una clase reutilizable, para cooperar con otras clases que no tengan, necesaria ni previsiblemente, interfaces compatibles. (sólo en la versión para objetos) Cuando se quieren usar varias subclases ya existentes, pero no resulta práctico adaptarlas una a una mediante herencia. En vez de esto, se puede adaptar la interfaz de la clase de la cual todas ellas heredan (y especializan) su comportamiento. Ventajas A nivel de clases... - 6 -

Facilidad para redefinir el comportamiento de la clase adaptada. Simplicidad (un sólo objeto, no hay punteros ni indirecciones adicionales). A nivel de objetos... Flexibilidad para que un sólo adaptador trabaje con muchas clases a adaptar (en concreto, puede hacerlo con toda una jerarquía de clases). Extensibilidad, puesto que se pueden añadir funcionalidades a todas las clases adaptadas a la vez. Inconvenientes A nivel de clases... Inflexibilidad, puesto que un sólo adaptador no puede trabajar con una clase y sus hijos a la vez. A nivel de objetos... Dificultad para redefinir el comportamiento de la clase adaptada. Relacionado con Puente tiene una estructura similar pese a ser su objetivo diferente (separar interfaz de implementación). Decorador es más transparente dado que mejora un objeto sin cambiar su interfaz. Apoderado define un delegado para un objeto sin tocar tampoco su interfaz. Otros aspectos de interés En el adaptador a nivel de clase, adaptador hereda públicamente la interfaz de objetivo y privadamente la implementación de la clase a adaptar. Un adaptador enchufable es una clase que tiene ya definidas internamente las posibles adaptaciones de su interfaz. Los adaptadores de doble sentido sirven para obtener transparencia ante diferentes clientes. El adaptador a nivel de objeto requiere un poco más de esfuerzo que el adaptador a nivel de clase, pero, a la larga, resulta más flexible! Ejemplo de aplicación En un editor gráfico de figuras lo fundamental es tener una abstracción que represente la forma de cualquier elemento gráfico genérico. Para conformar elementos ya existentes, nuevos o excesivamente complejos con la interfaz definida para esta forma genérica podemos usar un adaptador (en este caso, a nivel de objetos). EDITOR GRAFICO FORMA Contorno() VISTA DE UN TEXTO ObtenerExtensión() FORMA DE LÍNEA Contorno() APODERADO / PROXY FORMA DE TEXTO Contorno() texto texto -> ObtenerExtensión() Tipo - 7 -

Estructura, a nivel de objetos. Propósito Proporcionar un representante o delegado que se encargue de controlar el acceso a un objeto, generalmente por motivos de eficiencia. Estructura CLIENTE ELEMENTO Petición() ELEMENTO REAL Petición() Elemento Real APODERADO Petición() ElementoReal -> Petición() Cuando usarlo En cualquier situación en que sea necesaria una referencia a un objeto más versátil y/o sofisticada que un simple puntero. Por ejemplo : Un apoderado remoto proporciona un representante local para un objeto en un espacio de direcciones diferente (J.Coplien los llama embajadores). Un apoderado virtual crea por demanda objetos costosos. Un apoderado de protección restringe, por motivos de seguridad, el acceso a un objeto. Una referencia inteligente es una sustitución por un simple puntero, que incorpora servicios adicionales como cuenta del nº de referencias, carga de objetos persistentes en memoria cuando estos son referenciados y uso de cerrojos para controlar el acceso exclusivo a regiones críticas. Ventajas Se introduce un nivel de indirección en el acceso al objeto, que permite al apoderado remoto ocultar el hecho de que el objeto reside en un espacio de direcciones distinto, al apoderado virtual realizar optimizaciones como la creación de objetos por demanda y al apoderado de protección y a las referencias inteligentes realizar tareas adicionales de vigilancia sobre el objeto al que se accede. No obstante todo esto puede resultar un inconveniente, por motivos de claridad e inteligibilidad del diseño. Facilita otra optimización, relacionada con la creación de objetos por demanda : la técnica de COPY-ON-WRITE, que sólo hace efectiva la copia de un objeto oneroso cuando el acceso a él es de escritura, no de lectura. Relacionado con Adaptador proporciona al objeto que está adaptando una interfaz diferente, mientras que Apoderado presenta la misma interfaz que su representado. No obstante, en el caso del apoderado de protección se pueden rechazar peticiones que el representado sí puede atender, con lo que, de hecho, se está modificando su interfaz. - 8 -

Decorador puede tener una implementación similar a la de Apoderado, a pesar de tener una intención diferente : añadir algún comportamiento a un objeto, en vez de controlar el acceso al mismo. Diferentes apoderados varían en el grado de semejanza en su implementación con respecto a Decorador. Otros aspectos de interés El Apoderado es el encargado de crear y destruir los Elementos Reales cuando haga falta. Si el Apoderado puede tratar con el Elemento Real a través de una interfaz abstracta, entonces no es necesario tener una clase Apoderado por cada clase de Elemento Real. Pero si el Apoderado va a ser instanciado con un Elemento Real concreto, debe conocer de que clase es. Para poder representar al Elemento Real, el Apoderado debe tener una interfaz idéntica a la de Elemento. Una cuestión importante es : cómo hacer referencia al representado antes de instanciarlo? Un apoderado remoto debe responsabilizarse de empaquetar y enviar las peticiones y sus argumentos al objeto real. Un apoderado virtual puede almacenar información adicional relativa al objeto para posponer el acceso al mismo. Tanto un apoderado de protección como una referencia inteligente comprueban los permisos de acceso del cliente antes de pasar la petición al objeto. Ejemplo de aplicación En un editor de documentos que permite gráficas y dibujos complejos dentro de un documento se nos plantea el problema de que recuperar todos estos costosos elementos cada vez que se abre el documento es ineficiente e innecesario, por lo que podemos definir un representante, que ocupe su lugar, hasta que sea necesario cargarlos. EDITOR DE DOCUMENTOS GRÁFICO Dibujar() Guardar() Cargar() ObtenerContorno() IMAGEN Dibujar() Guardar() Cargar() imagen REPRESENTANTE - 9 - Dibujar() Guardar() Cargar() if (imagen == 0) imagen=cargarimagen(fichero); imagen -> Dibujar();

- 10 -

CADENA DE RESPONSABILIDADES / CHAIN OF RESPONSIBILITY Tipo Comportamiento, a nivel de objetos. Propósito Proporcionar a más de un objeto la capacidad de atender una petición, para así evitar el acoplamiento con el que objeto que hace la petición. Se forma con estos objetos una cadena, en la cual cada objeto o satisface la petición o la pasa al siguiente. Estructura CLIENTE RESPONSABLE AtenderPetición() sucesor RESPONSABLE CONCRETO 1 AtenderPetición() RESPONSABLE CONCRETO 2 AtenderPetición() Cuando usarlo Cuando una petición puede ser atendida por más de un objeto y el manejador que la satisfará no se conoce a priori. Cuando se quiere trasladar una petición a un objeto de entre unos cuantos, sin especificar explícitamente el receptor final. Cuando el conjunto de objetos que pueden atender una petición se puede especificar o modificar dinámicamente. Ventajas Se reduce el acoplamiento, puesto que se libera al objeto que hace la petición de conocer quien se la atiende. No sólo eso, sino que, además, los miembros de la cadena no conocen la estructura entera, sino sólo su sucesor en la misma. Mayor flexibilidad, puesto que se puede añadir o modificar la capacidad de atender una petición, simplemente haciendo cambios en la cadena de responsabilidades, dinámicamente (en tiempo de ejecución). Inconvenientes No se garantiza la recepción y satisfacción de una petición, pues puede haber errores en la configuración de la cadena o también puede ocurrir que ningún elemento de la cadena sepa atender la petición. Relacionado con Cadena de responsabilidades se usa frecuentemente junto a Composición, donde lo normal es que el sucesor de un componente en la cadena sea su ancestro en la estructura jerárquica recursiva. - 11 -

Muchas personas ven Cadena de Responsabilidades como una Estrategia recursiva o distribuida, donde el segundo encapsula unos algoritmos y el primero el criterio necesario para seleccionar un algoritmo concreto. Parece ser (se trata de una cuestión de interpretaciones y, por tanto, abierta) que una Estrategia recursiva es una Cadena de Responsabilidades, pero no al revés, porque los Responsables de ésta última pueden hacer más cosas aparte de encapsular un algoritmo, que es la única misión de la primera. Otros aspectos de interés Todos los Responsables en la cadena comparten una interfaz común, para garantizar la transparencia que nos permite evitar el acoplamiento. El Responsable padre de todos los Responsables Concretos puede, opcionalmente, implementar el enlace al sucesor, para que no tengan que hacerlo sus hijos o para ofrecer un mismo tipo de enlace a todos ellos (aunque pueden redefinirlo). En función de las circunstancias, se pueden aprovechar enlaces preexistentes entre objetos para implementar el enlace al sucesor o se pueden definir otros nuevos. Puede haber un conjunto fijo e inflexible de peticiones que los Responsables atienden, lo cual aumenta la sencillez y seguridad del sistema, o se puede permitir una mayor flexibilidad en el tipo de peticiones mediante PARAMETRIZACIÓN, siempre y cuando el cliente y los manejadores se pongan de acuerdo acerca del número, tipo y significado de los parámetros. Ejemplo de aplicación En un sistema de ayuda dependiente del contexto para una interfaz gráfica de usuario (GUI) se pretende que el usuario, pulsando el ratón sobre un elemento gráfico cualquiera, pueda obtener información de ayuda referente al mismo, siendo ésta distinta según sea la situación de ese elemento dentro de la interfaz (no es lo mismo un botón en una caja de diálogo que en la ventana principal de una aplicación). Así, cada elemento gráfico (un botón, por ejemplo), si puede, debe proporcionar esa información de ayuda y si no, debe pasar la petición al elemento que define el contexto en el que se encuentra (la caja de diálogo, por ejemplo), con lo que no se sabe a priori quién atenderá, finalmente, la petición, proporcionando la necesaria información de ayuda. GESTOR DE AYUDA - 12 -

contexto AtenderPeticiónDeAyuda() contexto -> AtenderPeticiónDeAyuda() APLICACIÓN ELEMENTO GRÁFICO DIÁLOGO BOTÓN MostrarAyuda() AtenderPeticiónDeAyuda() si puede dar la ayuda MostrarAyuda(); si no contexto::atenderpeticióndeayuda(); - 13 -

COMPOSICIÓN / COMPOSITE Tipo Estructura, a nivel de objetos. Propósito Permitir a los clientes tratar uniformemente a los objetos simples y compuestos de una estructura jerárquica recursiva. Estructura COMPONENTE CLIENTE Operación() SIMPLE COMPUESTO hijos Operación() Operación() para todos los hijos hijo.operación(); Cuando usarlo Cuando se pretende representar una jerarquía recursiva de objetos. Cuando se pretende que los clientes no reparen en las diferencias entre objetos simples y compuestos. Ventajas Simplifica notablemente al cliente, al no tener éste que distinguir entre objetos simples y compuestos. Favorece la extensibilidad, ya que es muy fácil añadir nuevos tipos de componentes, tanto simples como compuestos. Inconvenientes Puede hacer el diseño peligrosamente genérico, dificultando la imposición de restricciones sobre ciertos componentes de la jerarquía (por ejemplo, las comprobaciones de tipo no se pueden hacer con garantía más que en tiempo de ejecución). Esta es la otra cara de la facilidad para la extensibilidad. Relacionado con Es frecuente que la relación entre un componente y su padre se use para una Cadena de Responsabilidades. Decorador es muy frecuentemente usado junto a Composición, como un hijo más del padre común de la jerarquía ( Componente ), por lo que debe adaptarse a su interfaz. - 14 -

PesoMosca permite la compartición de componentes, pero presenta problemas a la hora de hacer referencia a los padres (ambigüedad por tener un componente varios padres). Iterador se usa para recorrer jerarquías de composición recursiva. Visitante localiza operaciones y comportamientos que de otro modo estarían dispersos entre las clases Simple y Compuesto. Otros aspectos de interés El cliente sólo trata con un componente genérico, no pudiendo, por tanto, distinguir si es simple o compuesto. Componente puede tener algún mecanismo para acceder al padre en la jerarquía de cada objeto (necesario para Cadena de Responsabilidades). Cuanto mayor sea la interfaz de Componente mayor será la uniformidad (=transparencia) con la que el cliente trata a los distintos elementos, pero eso tiene el inconveniente de que un elemento simple hereda operaciones que sólo tienen sentido para elementos compuestos. Si las operaciones de gestión de los hijos (Poner, Quitar, etc...) se ponen en Componente prima la TRANSPARENCIA sobre la SEGURIDAD. Si se ponen en Compuesto sucede al contrario. La estructura de datos utilizada para representar a los hijos depende de las circunstancias de cada caso, siempre en aras de la EFICIENCIA (ver Intérprete). Si los hijos están ordenados de alguna forma, el acceso y la gestión de los mismos debe ser especialmente cuidadosa (ver Iterador). Además, salvo en lenguajes con recolección de basura, la eliminación de los hijos es tarea del padre. Ejemplo de aplicación Un editor de dibujos permite al usuario construir complejas composiciones a partir de elementos básicos, que se ensamblan unos en/con otros. Utilizando el patrón Composición podemos usar adecuadamente la composición recursiva para ocultar al cliente las diferencias entre elementos gráficos sencillos y compuestos. ELEMENTO GRÁFICO Dibujar() ObtenerHijo(int) Quitar(Componente) Añadir(Componente c) RECTÁNGULO LÍNEA TEXTO DIBUJO componentes Dibujar() Dibujar() Dibujar() CONSTRUCTOR / BUILDER Dibujar() ObtenerHijo(int) Quitar(Componente) Añadir(Componente c) - 15 - para todos los componentes c.dibujar(); añadir c a la lista de componentes;

Tipo Creación, a nivel de objetos. Propósito Separar la construcción y la representación de un objeto complejo, para así permitir que el mismo proceso de construcción sirva para crear diferentes representaciones. Estructura DIRECTOR Construir() constructor CONSTRUCTOR ConstruirParte() para todos los objetos de la estructura {constructor->construirparte();} CONSTRUCTOR CONCRETO ConstruirParte() ObtenerResultado() PRODUCTO Cuando usarlo Cuando el algoritmo de creación del objeto complejo debe ser independiente de qué partes y cómo lo componen. Cuando el proceso de construcción debe soportar diferentes representaciones para el objeto que se construye. Ventajas El diseño gana en flexibilidad, dado que cambiar la representación interna del producto que se construye es tan sencillo como definir un nuevo tipo de constructor. La separación (independencia) entre el proceso de construcción y la representación del producto fomenta la reutilización, puesto que permite que diferentes directores construyan variantes de un producto a partir del mismo conjunto de partes. Se favorece el encapsulamiento y el control, puesto que cada constructor concreto contiene todo el código necesario para crear y ensamblar todas las partes de un producto y además el constructor crea el producto paso a paso (parte a parte) bajo la supervisión del director, que al final recibe el producto completo, de manos del constructor. Relacionado con Como constructor de objetos complejos, este patrón es similar a Fábrica Abstracta. La diferencia reside en que Constructor se centra en la creación de los objetos paso a paso (parte a parte), mientras Fábrica Abstracta está orientado a familias de - 16 -

objetos (simples o complejos). Además, en el primero el resultado se obtiene en el último paso y en el segundo se obtiene inmediatamente. Las estructuras de los objetos complejos que crea este patrón nos llevan frecuentemente al patrón Composición. Otros aspectos de interés Constructor suele ser una clase abstracta, por lo que ConstruirParte es una operación abstracta; en concreto, una por cada tipo de parte del objeto complejo. En C++, suelen ser métodos vacíos, no virtuales puros! En general no tiene sentido contemplar una clase abstracta de productos, dada la heterogeneidad de los mismos. La operación Construir, por lo general, es una sucesión de peticiones de construcción de partes, pero, a veces, es necesario acceder a partes de la estructura ya construidas (o acciones similares). La función ObtenerResultado es de suma importancia, ya que a través de ella el Director puede conseguir el producto final, una vez construidas todas sus partes y ensambladas. Ejemplo de aplicación Un proceso que lea documentos en el formato de intercambio RTF (Rich Text Format) debe ser capaz de convertirlo a otros muchos formatos de texto. El problema es que el nº de los mismos es abierto y desconocido, por lo que debe ser fácil añadir uno nuevo sin tocar al proceso que lee los documentos en RTF. - 17 -

LECTOR RTF constructor CONVERSOR DE TEXTO constructores TraducirRTF() ConvertirCarácter(char) ConvertirCambioDeFuente(fuente) ConvertirParrafo() while (t = siguiente token) { switch t.tipo { CHAR : constructor->convertircaracter(t.char); FUENTE : constructor->convertircambio DeFuente(t.Fuente); PÁRRAFO : constructor->convertirparrafo(); } } CONVERSOR A ASCII ConvertirCarácter(char) ObtenerTextoEnAscii() CONVERSOR A ELEMENTOS GRÁFICOS DE TEXTO ConvertirCarácter(char) ConvertirCambioDeFuente(fuente) ConvertirParrafo() ObtenerElementoGráficoDeTexto() CONVERSOR A T E X ConvertirCarácter(char) ConvertirCambioDeFuente(fuente) ConvertirParrafo() ObtenerTextoEnT E X() Texto en Ascii Elemento Gráfico de Texto Texto en T E X - 18 -

DECORADOR / DECORATOR Tipo Estructura, a nivel de objetos. Propósito Añadir responsabilidades adicionales a un objeto dinámicamente, proporcionando una alternativa flexible a la especialización mediante herencia, cuando se trata de añadir funcionalidades. Estructura COMPONENTE Operación() COMPONENTE CONCRETO Operación() DECORADOR Operación() componente componente -> Operación; Decorador::Operación(); Comportamiento(); DECORADOR CONCRETO A Comportamiento() Operación() DECORADOR CONCRETO B Operación() EstadoAnidado Cuando usarlo Cuando se quiere añadir responsabilidades a un objeto de manera dinámica y transparente (independientemente de otros objetos). Cuando es imposible la extensión de funcionalidad por herencia, por ser aquella imprevisible en tipo y número. Ventajas Aporta una mayor flexibilidad que la herencia estática, permitiendo, entre otras cosas, añadir una funcionalidad dos o más veces. Evita concentrar en lo alto de la jerarquía clases guiadas por las responsabilidades, es decir, que pretenden (en vano) satisfacer todas las posibilidades. De esta forma las nuevas funcionalidades se componen de piezas simples que se crean y se combinan con facilidad, independientemente de los objetos cuyo comportamiento extienden. Inconvenientes La transparencia tiene el inconveniente de que, a pesar de ser diferentes por muchos motivos, un decorador y un componente son indistinguibles, por lo que no se puede confiar en la identidad de los objetos. - 19 -

Gran fragmentación 5 ; el sistema se llena de gran cantidad de objetos pequeños, lo cual puede dificultar el aprendizaje de su funcionamiento y su depuración, aunque el que lo domine puede adaptarlo fácilmente. Relacionado con Adaptador cambia la interfaz de un objeto (ocasionalmente puede tener que añadir alguna funcionalidad) mientras que Decorador centra su atención en ampliar las responsabilidades de un objeto, sin tocar su interfaz. Decorador puede ser visto como una degeneración de Composición con un sólo componente, que además extiende funcionalidades. Decorador permite cambiar la piel de un objeto, mientras que Estrategia cambia sus entrañas. Esto hace que frente a la TRANSPARENCIA que da Decorador respecto a los componentes, Estrategia presenta una interfaz propia e independiente, que no tiene porque amoldarse a la de los componentes 6. Otros aspectos de interés Componente debe permanecer lo más ligera posible, definiendo una interfaz genérica y simple, para no arrastrar hacia complejidades innecesarias a Componentes Concretos y Decoradores (ver Composición). Un Decorador puede convertirse en una solución muy costosa si los componentes son, por naturaleza, muy complejos. En esos casos es preferible Estrategia. Puede resultar problemático especializar mediante herencia los Componentes Concretos, por culpa de la coherencia que el Decorador debe guardar, en cuanto a interfaz se refiere, con la clase base ( Componente ). Ejemplo de aplicación En los conjuntos de utilidades para interfaces gráficas de usuario (GUI) se puede permitir añadir a los componentes visuales propiedades (por ejemplo, un borde) o comportamientos (por ejemplo, una barra de desplazamiento). COMPONENTE VISUAL Dibujar() VISTA DE UN TEXTO Dibujar() Decorador::Dibujar(); DibujarBorde(); DECORADOR Dibujar() componente componente -> Dibujar(); BORDE DibujarBorde() Dibujar() AnchoDelBorde BARRA DE DESPLAZAMIENTO Dibujar() DesplazarHasta() PosiciónDeDesplazamiento 5 Esta es la esencia del paradigma orientado a objetos, luego no veo porque ha de ser un inconveniente. 6 Los autores de este catálogo parecen replantearse la bondad de Decorador y se inclinan por Estrategia. - 20 -

ESTADO / STATE Tipo Comportamiento, a nivel de objetos. Propósito Permitir a un objeto modificar su comportamiento a medida que su estado interno va cambiando, dando así la impresión de que el objeto cambia de clase. Estructura CONTEXTO Petición() estado ESTADO Atender() estado -> Atender(); ESTADO CONCRETO A Atender() ESTADO CONCRETO B Atender() Cuando usarlo Cuando el comportamiento de un objeto depende de su estado y debe poder cambiar dinámicamente (en tiempo de ejecución) dicho comportamiento, a medida que cambie dicho estado. Cuando las operaciones tienen definiciones largas y con múltiples condiciones, dependientes del estado del objeto, siendo lo más adecuado separar en objetos independientes cada condición atómica, para poder así combinarlas y modificarlas independientemente, ya sea en estados ya existentes, ya en otros nuevos que se formen combinándolos. Ventajas Dado que el comportamiento específico de cada estado está autocontenido en cada estado concreto, existe una gran flexibilidad para añadir nuevos estados y transiciones, mediante la definición de nuevas subclases. A pesar de que la distribución del comportamiento ante diferentes situaciones entre diferentes objetos incrementa el nº de clases y reduce la compacidad, es la mejor solución cuando hay muchos estados, pues evita las definiciones multicondicionales y grandes, tan indeseables como los procedimientos gigantes lo son en el estilo imperativo. Se hacen más explícitas las transiciones entre estados que sí todo estuviera concentrado en una sola clase (esto hace más inteligible el diseño), impidiendo además los estados internos inconsistentes (desde el punto de vista del contexto, los cambios de estado son ATÓMICOS). Si los objetos que representan los estados no tienen variables de instancia (esto es, el estado está totalmente definido en su propio tipo) entonces diferentes contextos pueden compartir estados, como PesoMosca sin estado intrínseco, sólo comportamiento. Relacionado con - 21 -

PesoMosca explica como los objetos Estado pueden ser compartidos. Los objetos Estado a menudo son Solitarios. Otros aspectos de interés La misión de Contexto es definir la interfaz que interesa a los clientes, mientras mantiene una referencia al Estado actual. Si dicho Estado necesita tener acceso al Contexto al que está asociado, éste puede pasarse a si mismo como parámetro de la petición. Si los estados que van a hacer falta no se conocen a priori y el Contexto cambia de Estado poco frecuentemente, es mejor ir creando/destruyendo estados sobre la marcha. Pero si el Contexto cambia constantemente de Estado es preferible crear todos los estados al comienzo y no destruirlos nunca (pueden volver a hacer falta). Las transiciones entre estados pueden estar prefijadas a priori en el Contexto o pueden dejarse a la responsabilidad de cada estado, que tendrá entonces que saber quien le sucede (aparte de este inconveniente, esta solución es más flexible y, por ello, preferible). Otra alternativa es una transición entre estados definida tabularmente. Esto permite cambiar el criterio de transición cambiando solamente los datos de entrada, pero es menos eficiente, hace menos explícitas las transiciones entre estados y dificulta el añadir acciones a dichas transiciones 7. Algunos lenguajes (Self) permiten a un objeto cambiar de clase en tiempo de ejecución, en lo que constituye una especie de herencia dinámica; esto es, soportan directamente este patrón. Ejemplo de aplicación Para cualquier protocolo de comunicaciones el comportamiento que manifiesta depende directamente del estado en que se encuentre : conectado, escuchando, cerrado, etc... CONEXIÓN_TCP Abrir() Cerrar() MandarConfirmación() estado ESTADO_TCP Abrir() Cerrar() MandarConfirmación() TCP_CONECTADO TCP_ESCUCHANDO TCP_CERRADO estado -> Abrir(); Abrir() Cerrar() MandarConfirmación() Abrir() Cerrar() MandarConfirmación() Abrir() Cerrar() MandarConfirmación() ESTRATEGIA / STRATEGY 7 Estado centra su atención en el comportamiento dependiente del estado y la aproximación basada en tablas en las transiciones entre estados! - 22 -

Tipo Comportamiento, a nivel de objetos. Propósito Definir una familia de algoritmos encapsulando por separado cada uno de ellos y haciéndolos, por tanto, intercambiables. Esto permite a los algoritmos variar con independencia de los clientes que los usan. Estructura CONTEXTO InterfazDelContexto() estrategia ESTRATEGIA InterfazDelAlgoritmo() estrategia -> InterfazDelAlgoritmo(); ESTRATEGIA CONCRETA A InterfazDelAlgoritmo() ESTRATEGIA CONCRETO B InterfazDelAlgoritmo() Cuando usarlo Cuando muchas clases relacionadas sólo se diferencian en su comportamiento. Cuando se necesitan diferentes variantes de un algoritmo. Cuando un algoritmo usa datos que los clientes no tienen porque conocer. Cuando una clase define muchos comportamientos, los cuales se manifiestan como definiciones condicionales múltiples de sus operaciones. Ventajas Las familias jerárquicas de estrategias definen algoritmos y comportamientos que enfatizan la reutilización. La herencia puede ayudar a sacar factor común a la funcionalidad de los algoritmos. El encapsulamiento de algoritmos en clases separadas ofrece una ventajosa alternativa a la especialización por herencia del contexto para obtener un comportamiento diferente, que promueve la independencia, la facilidad de entender el diseño y la posibilidad de futuras extensiones. Se eliminan las costosas definiciones de comportamiento multicondicionales. Se posibilita ofrecer diferentes implementaciones del mismo comportamiento, en función de restricciones como el espacio en memoria o el tiempo de respuesta. Inconvenientes Los clientes deben tener un cierto conocimiento de cada estrategia, para así poder elegir en cada situación cual es la más apropiada. Dado que todas las estrategias comportan una interfaz común, si las diferencias entre ellas es grande, es probable que mucha de la información que se les pasa no sea de utilidad más que a las más complejas. Puede producirse una gran explosión en el número de objetos del sistema. Esto se puede aliviar si las estrategias se implementan como objetos sin estado que los contextos pueden compartir (ver PesoMosca). - 23 -

Relacionado con Los objetos Estrategia a menudo son buenos PesosMosca. Otros aspectos de interés Si el Contexto pasa a la Estrategia los datos como parámetros de las operaciones de esta última se mantiene un acoplamiento débil, pero la eficiencia se puede resentir (puede que haya Estrategias que reciban datos que no necesitan). Si el Contexto se pasa a sí mismo como parámetro o la Estrategia mantiene una referencia al Contexto se resuelve este último problema a cambio de un mayor acoplamiento. Los clientes configuran al Contexto con una Estrategia determinada, con la cual el Contexto interactúa para producir un comportamiento determinado. Para tal fin, el Contexto puede definir una interfaz que permita a la Estrategia acceder a sus datos internos. Existe la posibilidad de que el Contexto defina un comportamiento por defecto y sólo en el caso de que los clientes deseen otra cosa se le configure con la Estrategia correspondiente. En C++, en el caso de que la Estrategia se fije en tiempo de compilación y se vaya a cambiar en ejecución se pueden usar plantillas (templates) para configurar un Contexto con una Estrategia. Ejemplo de aplicación En un editor de texto pueden existir múltiples algoritmos para dividir un documento en lineas (algoritmo simple, algoritmo T E X, algoritmo matricial, etc...), siendo deseable que la complejidad de los mismos quede oculta al cliente y que sea fácil y cómodo el cambio sobre la marcha de uno por otro o la adición de nuevos algoritmos al sistema. DOCUMENTO algoritmo Recorrer() Repaginar() algoritmo -> DividirEnLineas(); ALGORITMO DividirEnLineas() ALGORITMO T E X DividirEnLineas() ALGORITMO SIMPLE DividirEnLineas() ALGORITMO MATRICIAL DividirEnLineas() - 24 -

FÁBRICA ABSTRACTA / ABSTRACT FACTORY Tipo Creación, a nivel de objetos. Propósito Proporcionar una interfaz para la creación de familias de objetos interdependientes o interrelacionados, sin especificar sus clases concretas. Estructura PRODUCTO ABSTRACTO A CLIENTE PRODUCTO ABSTRACTO B PRODUCTO-A2 PRODUCTO-A1 PRODUCTO-B2 PRODUCTO-B1 FABRICA ABSTRACTA CrearProductoA() CrearProductoB() FABRICA CONCRETA 1 CrearProductoA() CrearProductoB() FABRICA CONCRETA 2 CrearProductoA() CrearProductoB() Cuando usarlo Cuando el sistema debe ser independiente de como sus productos se crean, componen y representan. Cuando el sistema debe configurarse con una familia de productos de entre múltiples posibles. Cuando se quiere dar énfasis a la restricción de que una familia de productos ha sido diseñada para que actúen todos juntos. Cuando se quiere proporcionar una librería de clases de productos, de los que sólo se desea revelar su interfaz, no su implementación. Ventajas - 25 -

Se potencia el encapsulamiento, puesto que se aísla a los clientes de las implementaciones. Se incrementa la flexibilidad del diseño, resultando fácil cambiar de familia de productos (recordemos que actúa toda junta). Se refuerza la consistencia, puesto que se restringe el uso a productos de una sola familia cada vez. Inconvenientes Se dificulta la extensibilidad, puesto que no es fácil añadir nuevos tipos de productos 8. Relacionado con La implementación de las clases contenidas en este patrón lleva, usualmente, a otros dos patrones : Método de Fábrica y Prototipo. Como lo más usual es que sólo necesitemos una fábrica concreta por familia de productos, esto nos allega al patrón Solitario. Otros aspectos de interés FábricaAbstracta no suele ser una clase abstracta en realidad, sino que, generalmente, proporciona una implementación básica o estándar de las operaciones, que será redefinida a voluntad por sus subclases. Ejemplo de aplicación En el diseño de una interfaz de usuario que dé soporte a múltiples estándares de presentación, como Motif o Presentation Manager, los diferentes estándares de presentación definen diferentes aspectos y comportamientos en elementos gráficos de la interfaz de usuario, tales como : barras de desplazamiento, ventanas o botones. VENTANA CLIENTE BARRA DE DESPLAZAMIENTO VENTANA MOTIF VENTANA PM BARRA MOTIF BARRA PM FABRICA DE ELEMENTOS GRÁFICOS CrearBarraDeDesplazamiento() CrearVentana() FABRICA DE ELEMENTOS PM CrearBarraDeDesplazamiento() CrearVentana() FABRICA DE ELEMENTOS MOTIF CrearBarraDeDesplazamiento() CrearVentana() FACHADA / FACADE 8 Existe un conflicto, ya clásico, entre la extensibilidad y la flexibilidad. - 26 -

Tipo Estructura, a nivel de objetos. Propósito Proporcionar una interfaz unificada de alto nivel que, representando a todo un subsistema, facilite su uso. La fachada satisface a la mayoría de los clientes, sin ocultar las funciones de menor nivel a aquellos que necesiten acceder a ellas. Estructura Cliente1 Cliente2 Cliente3 Cliente1 Cliente2 Cliente3 FACHADA Clase1 del subsistema Clase2 del subsistema Clase1 del subsistema Clase2 del subsistema Clase3 del subsistema Clase4 del subsistema Clase3 del subsistema Clase4 del subsistema Clase5 del subsistema SUBSISTEMA DE CLASES Clase5 del subsistema SUBSISTEMA DE CLASES Cuando usarlo Cuando se pretende proporcionar una interfaz simple para un subsistema complejo. Cuando existen muchas dependencias entre los clientes y las clases que implementan una abstracción. Una fachada proporciona al subsistema independencia y portabilidad. Cuando se pretende estructurar en capas el subsistema (cada capa tendrá su propia fachada ). Ventajas Al separar al cliente de los componentes del subsistema, se reduce el número de objetos con los que el cliente trata, facilitando así el uso del subsistema. Se promueve un acoplamiento débil entre el subsistema y sus clientes, eliminándose o reduciéndose las dependencias. No existen obstáculos para que las aplicaciones usen las clases del subsistema que necesiten. De esta forma podemos elegir entre facilidad de uso y generalidad. Relacionado con - 27 -

Fábrica Abstracta puede usarse conjuntamente con Fachada para proporcionar una interfaz que permita crear objetos del subsistema de manera independiente a éste. Además, puede ser una alternativa para ocultar las clases específicas de una plataforma. Mediador es similar a Fachada pues también abstrae la funcionalidad de clases ya existentes, pero está orientado a la comunicación entre objetos colegas y además suele centralizar aquellas responsabilidades que no competen a ninguno de ellos. Por su parte, como hemos visto, Fachada abstrae la interfaz de un subsistema para facilitar su uso, sin añadir funcionalidades y resultando transparente a éste. Lo más frecuente es que sólo haya un objeto Fachada de cada tipo. De ahí su relación con Solitario. Otros aspectos de interés La Fachada sabe qué clase es responsable de cada petición, pero es completamente transparente para ellas. Por tanto, aunque las funciones las desempeñan las otras clases, es a la Fachada a quien le toca el trabajo de traducir. Una manera de reducir el acoplamiento es hacer abstracta la Fachada y luego especializar mediante herencia. Otra posibilidad es configurar la Fachada con objetos del subsistema, que pueden cambiarse. Esta posibilidad puede entrar en conflicto con el objetivo de la Fachada, la facilidad de uso. Un subsistema es análogo a una clase, en el sentido de que tiene una interfaz PÚBLICA (de la que forma parte la Fachada ) y otra PRIVADA ( que no está muy claro como conseguirla ni para que sirve!). Ejemplo de aplicación En un entorno de programación se permite a las aplicaciones el acceso al subsistema de compilación. Este subsistema contiene clases como el AnalizadorLéxico, el AnalizadorSintáctico, el AnalizadorSemántico, el GeneradorDeCódigoIntermedio o el GeneradorDeCódigoFinal. No obstante sólo aplicaciones muy especiales necesitan acceder directamente a algunas de estas clases, mientras que para el resto se puede definir una interfaz general, una fachada, que les permita sencillamente compilar sus programas. CLASES DEL SUBSISTEMA DE COMPILACIÓN COMPILADOR Compilar() Cadena CadenaEnCódigoBit AnalizadorLéxico AnalizadorSintáctico ConstructorDeNodosDePrograma Token Símbolo NodoDePrograma GeneradorDeCódigo NodoDeDefinición GeneradorDeCódigo para una Máquina de Pila INTÉRPRETE / INTERPRETER GeneradorDeCódigo para una Máquina RISC NodoDeVariable NodoDeExpresión - 28 -

Tipo Comportamiento, a nivel de clases. Propósito Dado un lenguaje, define una representación para su gramática junto con un intérprete que usa dicha representación para interpretar sentencias en ese lenguaje. Estructura CLIENTE EXPRESIÓN ABSTRACTA Interpretar(contexto) CONTEXTO EXPRESIÓN TERMINAL Interpretar(contexto) EXPRESIÓN NO TERMINAL Interpretar(contexto) Cuando usarlo Principalmente, cuando haya un lenguaje que interpretar y sus diferentes construcciones puedan representarse mediante árboles sintácticos abstractos. Da sus mejores resultados cuando la gramática es simple (con gramáticas complejas la jerarquía de clases se hace inmanejable y es mejor usar generadores automáticos de analizadores sintácticos) y la eficiencia no es una cuestión vital (existen formas más eficientes de interpretar, usando máquinas de estado finitas en lugar de árboles sintácticos). Ventajas Facilidad para cambiar o extender la gramática, mediante herencia, dado que las diferentes reglas de la gramática se representan con clases. Facilidad para implementar la gramática, dado que las implementaciones de las clases nodo del árbol sintáctico son similares, pudiendo usarse para ello generadores automáticos de código. Facilidad para introducir nuevas formas de interpretar las expresiones en la gramática (tener en cuenta el patrón Visitante). Inconvenientes Limitación en el tipo de gramáticas (y, por extensión, de problemas) para los que sirve esta aproximación : simples y sin grandes necesidades de eficiencia. Aunque el uso de otros patrones puede mitigar este problema, hay circunstancias en que un Intérprete no es lo más apropiado. Relacionado con Considerado en su forma más general (una operación distribuida sobre una jerarquía de clases basada en el patrón Composición), prácticamente toda aparición de éste lleva unida la de un Intérprete. Pero es una cuestión de perspectiva ( subjetiva!) la que nos lleva a plantearnos un Intérprete sólo cuando la jerarquía de clases (árbol sintáctico) define un lenguaje. - 29 -

PesoMosca ofrece una forma de compartir los símbolos terminales del árbol sintáctico. El Intérprete puede usar un Iterador para recorrer la estructura. Visitante puede servir para mantener el comportamiento de cada nodo del árbol sintáctico abstracto en una sola clase. Otros aspectos de interés Si un tipo particular de problemas se presenta frecuentemente, puede ser provechoso expresar los diferentes casos del problema como sentencias de un lenguaje simple. Se puede, entonces, construir un intérprete que resuelva el problema interpretando dichas sentencias. Si es frecuente la creación de nuevos intérpretes o de nuevas formas de interpretar es mejor tener un Visitante, donde poner la operación a realizar fuera de la estructura de árbol. El Cliente construye (o recibe) una estructura de instancias de Expresiones terminales y Expresiones no terminales, ensambladas para formar un árbol sintáctico que representa la sentencia que se quiere interpretar, mientras que el Contexto contiene información global para el intérprete. A pesar de la similitud de la estructura de este patrón con la del patrón Composición hay sus diferencias, como que al Intérprete no le interesa como se construye el árbol sintáctico (eso es cosa del Cliente o de quien sea). Aunque la operación estrella es Interpretar, un Intérprete puede ser utilizado para realizar otra serie de operaciones sobre las sentencias de un lenguaje. Ejemplo de aplicación El problema de encontrar palabras que encajen en un patrón se puede resolver definiendo un lenguaje para ello, por ejemplo mediante Expresiones Regulares. Esto nos permite ya aplicar un Intérprete a dicho lenguaje para resolver el problema : repetición expresión :: = literal alternativa secuencia repetición literal :: = a b c... { a b c... } * alternativa :: = expresión expresión secuencia :: = expresión & expresión repetición :: = expresión * EXPRESIÓN REGULAR - 30 - Interpretar() expresión2 expresión1

- 31 -

ITERADOR / ITERATOR Tipo Comportamiento, a nivel de objetos. Propósito Proporcionar una forma de acceder secuencialmente a los elementos de un objeto compuesto por agregación sin necesidad de desvelar su representación interna. Estructura AGREGADO CrearIterador() CLIENTE ITERADOR Primero() Siguiente() Actual() AGREGADO CONCRETO CrearIterador() return new IteradorConcreto(this); ITERADOR CONCRETO Primero() Siguiente() Actual() Cuando usarlo Cuando se quiere acceder a los elementos de un objeto agregado sin mostrar su representación interna. Cuando se quieren permitir recorridos múltiples en objetos agregados. Cuando se quiere proporcionar una interfaz uniforme para recorrer diferentes estructuras de agregación (iteración polimórfica 9 ). Ventajas Se incrementa la flexibilidad, dado que para permitir nuevas formas de recorrer una estructura basta con modificar el iterador en uso, cambiarlo por otro ( parametrización!) o definir uno nuevo. Se enfatiza la distribución de responsabilidades (y, por ello, la simplicidad de los elementos del sistema), dado que la interfaz del agregado se ve libre de una serie de operaciones, más propias de la interfaz del iterador. Se facilitan el paralelismo y la concurrencia, puesto que, como cada iterador tiene consciencia de su estado en cada momento, es posible que dos o más iteradores recorran una misma estructura simultánea o solapadamente. Relacionado con Iterador se aplica a menudo a estructuras recursivas del tipo de Composición. Los Iteradores polimórficos se basan en Método de Fábrica a la hora de instanciar el tipo de iterador apropiado a cada caso. 9 Usar sólo en caso de necesidad. - 32 -