Descargar

Patrones Estructurales de Software (página 2)

Enviado por Pablo Turmero


Partes: 1, 2, 3
edu.red 11 Bridge / Handle (Puente) Propósito Desacoplar una abstracción de su implementación, de modo que los dos puedan cambiar independientemente. Motivación Clase que modela la abstracción con subclases que la implementan de distintos modos. Herencia hace difícil reutilizar abstracciones e implementaciones de forma independiente Si refinamos la abstracción en una nueva subclase, está tendrá tantas subclases como tenía su superclase. El código cliente es dependiente de la implementación.

edu.red 12 Bridge Aplicabilidad Se quiere evitar una ligadura permanente entre una abstracción y su implementación, p.e. porque se quiere elegir en tiempo de ejecución. Abstracciones e implementaciones son extensibles. Cambios en la implementación de una abstracción no deben afectar a los clientes (no recompilación). Ocultar a los clientes la implementación de la interfaz. Se tiene una proliferación de clases, como sucedía en la Motivación.

edu.red 13 Bridge Consecuencias Un objeto puede cambiar su implementación en tiempo de ejecución. Cambios en la implementación no requerirán compilar de nuevo la clase Abstracción y sus clientes. Se mejora la extensibilidad. Se ocultan detalles de implementación a los clientes.

edu.red 14 Bridge Implementación Aunque exista una única implementación puede usarse el patrón para evitar que un cliente se vea afectado si cambia. ¿Cómo, cuándo y dónde se decide que implementación usar? Constructor de la clase Abstraccion Elegir una implementación por defecto Delegar a otro objeto, por ejemplo un objeto factoría

edu.red 15 Ejemplo en Java 1.1 AWT La clase Component del paquete java.awt es una clase abstracta que encapsula la lógica común a todos los componentes GUI y tiene subclases tales como Button, List y TextField que encapsulan la lógica para estos componentes GUI de forma independiente de una plataforma concreta (Motif, W32, GTK,…). Por cada una de estas clases existe una interfaz (por ejemplo ComponentPeer, ButtonPeer, ListPeer,..) que declara métodos cuya implementación proporcionará la funcionalidad específica de una plataforma concreta. Existe una clase abstracta denominada Toolkit que contiene métodos abstractos para crear componentes para una plataforma concreta, tales como el método que crea un ButtonPeer o el que crea un ListPeer. Toolkit tiene una subclase para cada tipo de plataforma que implementan dichos métodos, también tiene una variable estática que almacena la única instancia que existirá de un toolkit concreto y un método estático getToolkit que retorna esa instancia. Cada clase componente (por ejemplo Button) tiene un atributo peer que se inicializa del siguiente modo (en este caso con un objeto ButtonPeer),

peer = getToolkit().createButton(this);

edu.red 16 Ejemplo Java 1.1 AWT Java 1.1 AWT (Abstract Window Toolkit) fue diseñado para proporcionar una interfaz GUI en un entorno heterogéneo.

AWT utiliza una factoría abstracta para crear todos los componentes peer requeridos para la plataforma específica que sea usada.

Ejemplo:

public class List extends Component implements ItemSelectable { … peer = getToolkit().createList(this); … }

El método getToolkit() es heredado de Component y devuelve una referencia al objeto factoría usado para crear todos los widgets

edu.red 17 // método getToolkit en Component

public Toolkit getToolkit() { return getToolkitImpl(); } final Toolkit getToolkitImpl() { ComponentPeer peer = this.peer; if ((peer != null) && ! (peer instanceof LightweightPeer)){ return peer.getToolkit(); } Container parent = this.parent; if (parent != null) { return parent.getToolkitImpl(); } return Toolkit.getDefaultToolkit(); } Ejemplo Java 1.1 AWT

edu.red 18 // método getDefaultToolkit en la clase Toolkit

public static Toolkit getDefaultToolkit() { String nm; Class cls; if (toolkit == null) { try { nm = System.getProperty("awt.toolkit", "sun.awt.motif.MToolkit"); try { cls = Class.forName(nm); } catch (ClassNotFoundException e){..} if (cls != null) toolkit = (Toolkit) cls.newInstance(); … return toolkit; } Ejemplo en Java 1.1 AWT

edu.red 19 Composite (Compuesto) Propósito Componer objetos en estructuras jerárquicas para representar jerarquías parte/todo. Permite a los clientes manejar a los objetos primitivos y compuestos de forma uniforme. Motivación Modelar figuras compuestas Modelar documentos Modelar paquetes de valores (acciones, bonos,..)

edu.red 20 Composite Aplicabilidad Se quiere representar jerarquías parte/todo Se quiere que los clientes ignoren la diferencia entre objetos compuestos y los objetos individuales que los forman.

edu.red 21 Composite Consecuencias Jerarquía con clases que modelan objetos primitivos y objetos compuestos, que permite composición recursiva. Clientes pueden tratar objetos primitivos y compuestos de modo uniforme. Es fácil añadir nuevos tipos de componentes. No se puede confiar al sistema de tipos que asegure que un objeto compuesto sólo contendrá objetos de ciertas clases, necesidad de comprobaciones en tiempo de ejecución.

edu.red 22 Composite

Implementación Referencias de componentes hijos a su padre puede ayudar al recorrido y manejo de la estructura compuesta. ¿Debe contener Componente operaciones que no tienen significado para sus subclases? ¿Dónde colocamos las operaciones de añadir y eliminar hijos, y obtener hijos? Compromiso entre seguridad y transparencia. Transparencia: en clase Componente Seguridad: en clase Composite Puede ser necesario especificar un orden en los hijos. ¿Qué estructura de datos es la adecuada?

edu.red 23 Decorator (Decorador) Propósito Asignar dinámicamente nuevas responsabilidades a un objeto. Alternativa más flexible a crear subclases para extender la funcionalidad de una clase. Motivación Algunas veces se desea añadir atributos o comportamiento adicional a un objeto concreto no a una clase. Ejemplo: bordes o scrolling a una ventana. Herencia no lo permite.

edu.red 24 Decorador Aplicabilidad Añadir dinámicamente responsabilidades a objetos individuales de forma transparente, sin afectar a otros objetos. Responsabilidades de un objeto pueden ser eliminadas. Para evitar una explosión de clases que produce una jerarquía inmanejable.

edu.red 25 Decorador Consecuencias Más flexible que la herencia: responsabilidades pueden añadirse y eliminarse en tiempo de ejecución. Diferentes decoradores pueden ser conectados a un mismo objeto. Reduce el número de propiedades en las clases de la parte alta de la jerarquía. Es simple añadir nuevos decoradores de forma independiente a las clases que extienden. Un objeto decorador tiene diferente OID al del objeto que decora. Sistemas con muchos y pequeños objetos.

edu.red 26 Decorador Implementación La interfaz de un objeto decorador debe conformar con la interfaz del objeto que decora. Clases decorador deben heredar de una clase común. Componentes y decoradores deben heredar de una clase común que debe ser “ligera” en funcionalidad. Si la clase Componente no es ligera, es mejor usar el patrón Estrategia que permite alterar o extender el comportamiento de un objeto. Un componente no sabe nada acerca de sus decoradores, con Estrategia sucede lo contrario.

edu.red 27 Decorador Implementación El decorador envía los mensajes al componente que decora, pudiendo extender la operación con nuevo comportamiento. Las clases que modelan los decoradores concretos pueden añadir responsabilidades a las que heredan de Decorator.

Ejercicio. Muestra la diferencia entre aplicar el patrón Decorador y el patrón Estrategia para añadir funcionalidad a instancias de una clase TextView, tal como un borde o una barra de desplazamiento.

edu.red 28 Ejemplo Java Java posee una librería de clases e interfaces para manejar streams de caracteres y bytes. Por ejemplo, la clase abstracta Reader que proporciona un stream de caracteres tiene subclases tales como InputStreamReader o StringReader que implementan diferentes formas de proporcionar un stream de entrada de caracteres. También se dispone de una clase Writer para streams de salida de caracteres. Para cada uno de los tipos de stream la librería incluye unas clases que representan “filtros de stream” (filter) que permiten encadenar filtros sobre un stream y aplicarle varias transformaciones, como son las clases abstractas FilterReader y FilterWriter. A continuación se muestra parte del código de la clase FilterReader que implementa métodos de la clase Reader como read() y que es raíz de clases que implementan filtros de lectura.

public abstract class FilterReader extends Reader { protected Reader in; protected FilterReader(Reader in) { super(in); this.in = in; } public int read() throws IOException { return in.read(); } … }

edu.red 29 Ejemplo Java Podemos definir diferentes subclases de FilterReader con filtros tales como convertir a mayúsculas o eliminar espacios redundantes entre palabras. La siguiente clase sería un ejemplo:

public class ConversorMayúsculas extends FilterReader { public ConversorMayúsculas (Reader in) { super(in); } public int read() throws IOException { int c = super.read(); if (c != -1) return Character.toUpperCase((char)c); else return c; } }

edu.red 30 Facade (Fachada) Propósito Proporciona una única interfaz a un conjunto de clases de un subsistema. Define una interfaz de más alto nivel que facilita el uso de un subsistema. Motivación Reducir las dependencias entre subsistemas. Un entorno de programación que ofrece una librería de clases que proporcionan acceso a su subsistema compilador: Scanner, Parser, ProgramNode, ByteCodeStream y ProgramNodeBuilder. Clase Compiler actúa como fachada.

Partes: 1, 2, 3
 Página anterior Volver al principio del trabajoPágina siguiente