Programación II. Guía 13 1 Facultad: Ingeniería Escuela: Computación Asignatura: Programación II Tema: Patrones de Diseño. Objetivos Específicos Implementar la aplicación de patrones de diseño como herramientas para el mejoramiento de la programación. Desarrollar aplicaciones usando patrones de diseño. Comprender las ventajas de aplicaciones de patrones de diseño como manera profesional de elaborar software. Materiales y Equipo Computadora con el software DevC++. Guía Número 13. Introducción Teórica Concepto de Patrón. Un patrón de diseño es: Una solución estándar para un problema común de programación. Una técnica para flexibilizar el código haciéndolo satisfacer ciertos criterios. Un proyecto o estructura de implementación que logra una finalidad determinada. Un lenguaje de programación de alto nivel. Una manera más práctica de describir ciertos aspectos de la organización de un programa. Conexiones entre componentes de programas. La forma de un diagrama de objeto o de un modelo de objeto.
2 Programación II, Guía 13 Ejemplos de Patrones. A continuación se presentan algunos ejemplos de patrones de diseño. A cada diseño de proyecto le sigue el problema que trata de resolver, la solución que aporta y las posibles desventajas asociadas. Un desarrollador debe buscar un equilibrio entre las ventajas y las desventajas a la hora de decidir que patrón utilizar. Lo normal es, como observará a menudo en la ciencia computacional y en otros campos, buscar el balance entre flexibilidad y rendimiento. Encapsulación (ocultación de datos). Problema: los campos externos pueden ser manipulados directamente a partir del código externo, lo que conduce a violaciones del invariante de representación o a dependencias indeseables que impiden modificaciones en la implementación. Solución: esconda algunos componentes, permitiendo sólo accesos estilizados al objeto. Desventajas: la interfaz no puede, eficientemente, facilitar todas las operaciones deseadas. El acceso indirecto puede reducir el rendimiento. Subclase (herencia). Problema: abstracciones similares poseen miembros similares (campos y métodos). Esta repetición es tediosa, propensa a errores y un quebradero de cabeza durante el mantenimiento. Solución: herede miembros por defecto de una superclase, seleccione la implementación correcta a través de resoluciones sobre qué implementación debe ser ejecutada. Desventajas: el código para una clase está muy dividido, con lo que, potencialmente, se reduce la comprensión. La introducción de resoluciones en tiempo de ejecución introduce overhead (procesamiento extra).
Programación II. Guía 13 3 Iteración. Problema: los clientes que desean acceder a todos los miembros de una colección deben realizar un transversal especializado para cada estructura de datos, lo que introduce dependencias indeseables que impiden la ampliación del código a otras colecciones. Solución: las implementaciones, realizadas con conocimiento de la representación, realizan transversales y registran el proceso de iteración. El cliente recibe los resultados a través de una interfaz estándar. Desventajas: la implementación fija la orden de iteración, esto es, no está controlada en absoluto por el cliente. Excepciones. Problema: los problemas que ocurren en una parte del código normalmente han de ser manipulados en otro lugar. El código no debe desordenarse con rutinas de manipulación de error, ni con valores de retorno para identificación de errores. Solución: introducir estructuras de lenguaje para arrojar e interceptar excepciones. Desventajas: es posible que el código pueda continuar aún desordenado. Puede ser difícil saber dónde será gestionada una excepción. Tal vez induzca a los programadores a utilizar excepciones para controlar el flujo normal de ejecución, que es confuso y por lo general ineficaz. Cuando no utilizar patrones de diseño. La primera regla de los patrones de diseño coincide con la primera regla de la optimización: Del mismo modo que no es aconsejable optimizar prematuramente, no se deben utilizar patrones de diseño antes de tiempo. Seguramente sea mejor implementar algo primero y asegurarse de que funciona, para luego utilizar el patrón de diseño para mejorar las debilidades; esto es cierto, sobre todo, cuando aún no ha identificado todos los detalles del proyecto (si comprende totalmente el dominio y el problema, tal vez sea razonable utilizar
4 Programación II, Guía 13 patrones desde el principio, de igual modo que tiene sentido utilizar los algoritmos más eficientes desde el comienzo en algunas aplicaciones). Procedimiento EJEMPLO No. 1 - Patrón de diseño compuesto. Características: Identificar el escalar / clases primitivas y el vector / clases de contenedores. Crear una "interfaz" (mínimo común denominador) que pueden hacer todas las clases concretas "intercambiables". Todas las clases concretas declaran "una relación" a la interfaz. Todas las clases "contenedoras" se acoplan por ellas mismas a la interfaz (composición recursiva). Implementación de Patrón de diseño de comandos. #include<iostream> #include <vector> // Para utilizar la clase vector using namespace std; // Crea una "interfaz" class Component { public: virtual void traverse( ) = 0; ; class Leaf : public Component { private: int value; public: Leaf(int val) { value = val; // SuperClase Abstracta // Función virtual pura // Clase Escalar. Relación es un // Constructor con parámetros ; void traverse( ) { cout << value << ' '; // Función para mostrar los elementos del vector class Composite : public Component // Clase contenedora enlazada a la interfaz { private: // Clase Vector. Relación es un vector < Component * > children; // Contenedor enlazado con la interfaz
Programación II. Guía 13 5 public: void add(component * ele) /* Función para agregar elementos a la cola { children.push_back(ele); (vector) */ ; // Función recursiva para mostrar los elementos del vector void traverse( ) { for (int i = 0; i < children.size( ); i++) children [i] -> traverse( ); // Uso de polimorfismo para delegar al hijo int main( ) { Composite containers[4]; /* Crea un objeto de tipo Composite. En verdad se crea una matriz de 4 x n */ for (int i = 0; i < 4; i++) // Para agregar los datos a la primera fila(0) de la matriz for (int j = 0; j < 3; j++) containers [ i ].add(new Leaf(i * 3 + j)); for (int i = 1; i < 4; i++) // Agrega los elementos de las filas 2 a 4 en la matriz containers[0].add(&(containers[ i ])); for (int i = 0; i < 4; i++) // Rutina para mostrar todos los elementos de la matriz { cout << "Mostrando la fila " << i + 1 << endl; containers[i].traverse( ); cout << endl; system("pause > nul"); return 0; EJEMPLO No. 2 - Patrón de diseño Decorador. Características: Crear un "mínimo común denominador" que hace que las clases sean intercambiables. Crear una clase base de nivel dos para la funcionalidad opcional. La clase "Core" y "Decorador" declaran una relación "es un". La clase Decorador tiene una instancia del "mínimo común denominador". La clase Decorador delega para la de la clase tiene un objeto. Cree una clase Decorador derivado para cada adorno opcional. Decorador de las clases derivadas delega a la clase base y permite agregar cosas extras.
6 Programación II, Guía 13 El Cliente tiene la responsabilidad de componer configuraciones deseadas. #include <iostream> using namespace std; class Widget { public: virtual void draw( ) = 0; ; class TextField : public Widget { private: int width, height; public: TextField(int w, int h) { width = w; height = h; // Superclase Abstracta // Función virtual pura // Clase "Principal. Relación "es un" // Constructor con parámetros ; /* Función virtual para mostrar los datos del campo de texto void draw( ) { cout << "TextField: " << width << ", " << height << '\n'; class Decorator : public Widget { private: Widget * wid; public: Decorator(Widget * w) { wid = w; // Clase base de segundo nivel. Relación "es un" // Relación "tiene un" // Constructor con parámetros ; void draw() // Función virtual { wid -> draw( ); // Delegación a clase hija class BorderDecorator : public Decorator { public: BorderDecorator(Widget * w): Decorator(w){ // Embellecimiento opcional ; // Función virtual para mostrar los datos del borde del decorador void draw() { Decorator :: draw( ); // Delegar hacia la clase base y cosas extras cout << " Se ha invocado a la clase BorderDecorator " << endl;
Programación II. Guía 13 7 class ScrollDecorator : public Decorator { public: ScrollDecorator(Widget * w): Decorator(w){ // Embellecimiento opcional ; // Función virtual para mostrar los datos del scroll del decorador void draw() { Decorator :: draw( ); // Delegar hacia la clase base y cosas extras cout << " Se ha invocado a la clase ScrollDecorator " << endl; int main( ) { // El Cliente tiene la responsabilidad para componer configuraciones deseadas Widget * awidget = new BorderDecorator(new BorderDecorator(new ScrollDecorator(new TextField(80, 24)))); awidget -> draw( ); // Se invoca a la función draw con el puntero creado system("pause > nul"); return 0; Investigación Complementaria Investigar lo siguiente: Qué otros tipos de patrones de diseño existen? Explicar el problema, la solución y las ventajas. Investigar sobre el Patrón de Proxy el cual protege de acceso al objeto original. Incluir codificación.
8 Programación II, Guía 13 Guía 13: Patrones de Diseño. Hoja de cotejo: 13 Alumno: Máquina No: Docente: GL: Fecha: EVALUACIÓN % 1-4 5-7 8-10 Nota CONOCIMIENTO Del 20 al 30% Conocimiento deficiente de los fundamentos teóricos Conocimiento y explicación incompleta de los fundamentos teóricos Conocimiento completo y explicación clara de los fundamentos teóricos APLICACIÓN DEL CONOCIMIENTO Del 40% al 60% ACTITUD Del 15% al 30% No tiene actitud proactiva. Actitud propositiva y con propuestas no aplicables al contenido de la guía. Tiene actitud proactiva y sus propuestas son concretas. TOTAL 100%