miércoles, 13 de abril de 2050

Patrones de Diseño

Introducción

Un poco de historia
Los patrones se introducen en 1995 con el libro del llamado "GoF", de Gang of Four (en referencia a la "banda de los cuatro" autores), llamado "Design Patterns - Elements of Reusable Object-Oriented Software" escrito por Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides. Este libro constituye la obra de referencia acerca de patrones de diseño.

¿Qué es un patrón de diseño?
Se trata de soluciones conocidas y probadas cuyo diseño proviene de la experiencia de los programadores, por ende los patrones de diseño están basado en las buenas prácticas de la programación orientada a objetos.


¿Por qué usar patrones de diseño?
Los patrones de diseño se deben de usar puesto que facilitan la documentación y codificación de los sistemas, además de permitir reutilizar fácilmente buenos diseños y arquitecturas.

¿Cómo seleccionar un patrón de diseño?

Para seleccionar el o los patrones de diseño que resuelva el problema que nos atañe debemos considerar el propósito de cada patrón, estudiar la interrelación entre los patrones, así como, pensar en los aspectos que podrían cambiar dentro del sistema. 



viernes, 1 de mayo de 2026

Patrones de Estructuración

 Introducción

El objetivo de los patrones de estructuración es facilitar la independencia de la interfaz de un objeto o de un conjunto de objetos respecto de su implementación. En el caso de un conjunto de objetos, se trata también de hacer que esta interfaz sea independiente de la jerarquía de clases y de la composición de los objetos.
Proporcionando interfaces, los patrones de estructuración encapsulan la composición de objetos, aumentan el nivel de abstracción del sistema de forma similar a como los patrones de creación encapsulan la creación de objetos. Los patrones de estructuración ponen de relieve las interfaces.

La encapsulación de la composición no se realiza estructurando el objeto en sí mismo sino transfiriendo esta estructuración a un segundo objeto. Éste queda íntimamente ligado al primero. Esta transferencia de estructuración significa que el primer objeto posee la interfaz de cara a los clientes y administra la relación con el segundo objeto que gestiona la composición y no tiene ninguna interfaz con los clientes externos.
Fuente: Patrones de diseño en Java Los 23 modelos de diseño

miércoles, 4 de mayo de 2016

Patrón Proxy

PATRÓN PROXY

PROPÓSITO

Proporcionar un representante o delegado que se encargue de controlar el acceso
a un objeto, generalmente por motivos de eficiencia.

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 unespacio 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.

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. Observe la figura 1

figura 1

Desarrollemos el código ahora.
y de esta manera se implementa en la función Main.

Patrón Método Fábrica

PATRÓN FACTORY METHOD/MÉTODO FÁBRICA

¿CUAL ES EL PROPÓSITO? 

Permitir que una clase delegue la responsabilidad de la creación de objetos a sus subclases.


¿QUÉ MOTIVA A IMPLEMENTAR ESTE PATRÓN?


En el desarrollo de aplicaciones es común encontrarse con la creación de objetos que, aunque bien son diferentes, tienen algo en común, pertenecen a una misma familia por decirlo de alguna manera, un ejemplo de esto es la creación de documentos.  

Una clase Gaveta que hace parte de una clase Archivo, cuya responsabilidad es almacenar los documentos en una aplicación, necesitará crear instancias de algún tipo de documento especifico. Por ejemplo, se pueden crear documentos en Word, Hojas de calculo, PDF, etc vease la figura 1
Debido a que las subclases Documentos concretas para instanciar son especificas de su aplicación, la clase Gaveta no puede predecir qué subclase de Documento debe instanciar, es decir, la clase Gaveta solo sabe cuándo debe crearse un nuevo Documento, pero no qué tipo de Documento crear.



figura 1.

Este método propone una solución a este dilema.  Encapsula el conocimiento acerca de qué subclase de Documento crear y saca ese conocimiento fuera de la clase.

Las subclases de Archivo re definen su operación abstracta crearDocumento para que devuelva la subclase de Documento adecuada. llamaremos a este método crearDocumento un método de fabricación porque es el responsable de "fabricar" un objeto.


IMPLEMENTACIÓN

A la hora de aplicar debemos tener en cuenta dos cuestiones:


  1. pueden usarse métodos de fabricación parametrizados. es una variante de este patrón que permite que los métodos en los que se implementa la fabricación creen varios tipos de productos, en nuestro caso de Documento.
  2. cuando la clase creador, Gaveta para nuestro caso, es una clase concreta, es decir que no tiene subclases, y proporciona una implementación predeterminada del método de fabricación.  Para ser mas claros, es crear solo una clase Gaveta y que ella misma sea quien se encargue de crear los tipos de documentos según la lógica implementada por defecto en el método de fabricación, crearDocumento para nuestro caso.
  3. otra variante es cuando la clase creador, Gaveta para nuestro caso, es una clase abstracta y no proporciona una implementación para el método de fabricación que declara.
para ilustrar mejor estas tres variantes especifiquemos el problema de las gavetas del archivo.  Suponga que la clase Gaveta puede crear cualquier tipo de documento, por lo que para resolver este problema usando el método de fabricación, se hará uso de la primera variante descrita anteriormente, en donde se puede crear un método de fabricación parametrizado que reciba la extensión del documento y cree, ya sea, un Documento pdf si es .pdf, o Word si es .Doc, etc. vease la figura 1.1



figura 1.1

Ahora suponga que se pide que hayan diferentes restricciones, en donde  una gaveta deba contener un conjunto de documentos específicos, de oficio, o Pdf, entonces nuestra clase Gaveta seria abstracta y habría una subclase GavetaOficios y otra GavetaDigitalizados donde solo se crearán documentos Word y Pdf, respectivamente, para archivar, por lo que el método crearDocumento será abstracto y su implementación estará en la subclase Correspondiente, esto nos evita tener que instanciar objetos de tipo Documento Word o Pdf como caso especifico.  Solo cuando se cree una instancia de Gaveta tipo GavetaOficios o GavetaDigitalizados podremos crear Documentos Word o Pdf, llamando su método de fabricación crearDocumento. vease la figura 1.2

figura 1.2

La primera y segunda variante son muy parecidas, por lo que solo se desarrollará el código de la ultima.  Por otra parte, a modo de aprendizaje se dejará la implementación de la primera variante como ejercicio, será fácil, solo se debe desarrollar en la lógica del método fábrica  devolver una instancia según la extensión recibida.

Ahora si, vamos al código.  Empezamos creando la clase abstracta Gaveta.
Luego creamos las subclases GavetaDigitalizados y GavetaOficios, respectivamente.
Ahora Crearemos la Interfaz Documento y los tipos de documento Word y Pdf respectivamente.
Por ultimo creamos la clase Archive que tendrá un listado de gavetas creadas por defecto.
El siguiente código, es la implementación en main.

PATRÓN COMPOSITE

PATRÓN COMPOSITE
Objetivo:
·         Componer objetos en estructuras de árbol para representar jerarquías.
·         Manipular todos los objetos del árbol de manera uniforme.

¿Para qué sirve?
El patrón Composite sirve para construir objetos complejos a partir de otros más simples y similares entre sí, gracias a la composición recursiva y a una estructura en forma de árbol.
Este útil patrón permite crear y manejar estructuras de objetos en forma de árbol, en las que un objeto puede contener a otro(s).

¿Se debe utilizar Composite cuándo?
·         Se busca que el cliente puede ignorar la diferencia entre objetos primitivos y compuestos (para que pueda tratarlos de la misma manera).
·         Se quiere combinar objetos en estructuras de árbol para representar jerarquías de parte-todo.

Diagrama UML ¨Patrón Composite¨

  • Component: implementa un comportamiento común entre las clases y declara una interface de manipulación a los padres en la estructura recursiva.
  • Leaf: representa los objetos “hoja” (no poseen hijos). Define comportamientos para objetos primitivos.
  • Composite: define un comportamiento para objetos con hijos. Almacena componentes hijos, implementa operaciones de relación con los hijos.

Consecuencias
  •  Define jerarquías de clases hechas de objetos primitivos y compuestos.
  • Si el código cliente espera un objeto simple, puede recibir también uno compuesto z Simplifica el cliente.
  • Objetos simples y compuestos se tratan homogéneamente z Facilita la incorporación de nuevos tipos de componentes z Puede hacer el diseño demasiado general.
  • Es complicado restringir el tipo de componentes de un composite.

       Ejemplo:
             Vamos a realizar un ejemplo de un Banco. Un banco puede tener muchos sectores
  •      Gerencia.                 
  •      Administrativo. 
  •      RRHH. 
  •      Cajas. 

    Cada uno de estos sectores tendrá empleados que cobran un sueldo. En nuestro caso utilizaremos el Composite para calcular la sumatoria de sueldos de la empresa. 
      En el siguiente link, encontraras la implementación del patrón COMPOSITE  aplicado al ejemplo anteriormente planteado.
       https://github.com/rafaelnunez/TAcomposite


      Referencias bibliográficas:     

Template Method

DESCRIPCIÓN
El patrón de diseño Template Method forma parte de la familia de patrones denominados de comportamiento. Este tipo patrones ayudan a resolver problemas de interacción entre clases y objetos. Template Method nace de la necesidad de extender determinados comportamientos dentro de un mismo algoritmo por parte de diferentes entidades. Es decir, diferentes entidades tienen un comportamiento similar pero que difiere en determinados aspectos puntuales en función de la entidad concreta.

SOLUCIÓN INCORRECTA:
Una posible solución podría ser copiar el algoritmo en cada de las diferentes entidades cambiando la parte concreta en la que difieren. Esta solución tiene una consecuencia negativa ya que se genera código duplicado.

SOLUCIÓN CORRECTA:
La solución que propone el patrón Template Method es abstraer todo el comportamiento que comparten las entidades en una clase (abstracta) de la que, posteriormente, extenderán dichas entidades. Esta superclase definirá un método que contendrá el esqueleto de ese algoritmo común (método plantilla o template method) y delegará determinada responsabilidad en las clases hijas, mediante uno o varios métodos abstractos que deberán implementar.

REPRESENTACIÓN EN UML:

Como puede verse en el anterior diagrama, la superclase contiene el método plantilla, ese método con el algoritmo que comparten las entidades concretas (subclases). Como se puede apreciar, define una o varias operaciones concretas en forma de métodos abstractos que son usados por el método plantilla y que deben ser implementadas por las clases hijas. Dichos métodos abstractos representan los comportamientos concretos de las entidades.

DOMINIOS DE LA APLICACIÓN

El patrón se utiliza en los casos siguientes:
  1.      Una clase compartida con otra u otras clases con código idéntico que puede factorizarse siempre que las partes específicas a cada clase hayan sido desplazadas a nuevos métodos.
  2.     Un algoritmo posee una parte invariable y partes específicas a distintos tipos de objetos.

Ejemplo

En el sistema de venta online de vehículos, queremos gestionar pedidos de clientes de España y de Luxemburgo. La diferencia entre ambas peticiones concierne principalmente al cálculo del IVA. Si bien en España la tasa de IVA es siempre fija de21%, en el caso de Luxemburgo es variable (12% para los servicios, 15% para el material). El cálculo del IVA requiere dos operaciones delculo distintas en función del país.

Una primera solución consiste en implementar dos clases distintas sin súperclase común: PedidoEspaña y PedidoLuxemburgo. Esta solución presenta el inconveniente

importante de que tiene código idéntico que no ha sido factorizado, como por ejemplo la visualización de la información del pedido (método visualiza).

Podría incluirse una clase abstracta Pedido para factorizar los métodos comunes, como el método visualiza.

El patrón Template Method permite ir más lejos proponiendo factorizar el código común en el interior de los métodos. Tomemos el ejemplo del método calculaImporteConIVA cuyo algoritmo es el siguiente para España (escrito en pseudo- código).

calculaImporteConIVA:
importeIVA = importeSinIVA * 0,21;
importeConIVA = importeSinIVA + importeIVA;

El algoritmo para Luxemburgo tiene el siguiente pseudo-código.

calculaImporteConIVA:
importeIVA = (importeServiciosSinIVA * 0,12) + (importeMaterialSinIVA * 0,15);
importeConIVA = importeSinIVA + importeIVA;

Vemos en este ejemplo que la última línea del método es común a ambos países (en este ejemplo, sólo hay una línea común aunque en un caso real la parte común puede ser mucho más importante).

Reemplazamos la primera línea por una llamada a un nuevo método llamado calculaIVA. De este modo el método calculaImporteConIVA se describe en adelante de la siguiente forma:

calculaImporteConIVA:
calculaIVA();
importeConIVA = importeSinIVA + importeIVA;

El método calculaImporteConIVA puede ahora factorizarse. El código específico ha sido desplazado en el todo calculaIVA, cuya implementación es específica para cada país. El método calculaIVA se incluye en la clase Pedido como método abstracto.

El método calculaImporteConIVA se llama un método "modelo" (template method). Un método "modelo" incluye la parte común de un algoritmo que está complementado por partes específicas.

Esta solución se ilustra en el diagrama de clases de la figura 27.1 donde, por motivos de simplicidad, el cálculo del IVA de Luxemburgo se ha configurado con una tasa única
del 15%.

SOLUCIÓN EN JAVA
Descargue solución aquí

La clase abstracta Pedido incluye el método "modelo" calculaImporteConIVA que invoca al método abstracto calculaIVA.

La subclase concreta PedidoEspaña implementa el método calculaIVA con la tasa de
IVA español.


La subclase concreta PedidoLuxemburgo implementa el método calculaIVA con la tasa de IVA luxemburgués.


Por último, la clase TemplateMethod contiene el programa principal. Éste crea un pedido español, fija el importe sin IVA, calcula el importe con IVA y a continuación muestra el pedido. A continuación, el programa principal realiza la misma operación con un pedido luxemburgués.