patrones de diseño un curso practico 1

4
SOLO PROGRAMADORES Introducción El movimiento de los patrones de diseño se encuentra actualmente en auge. Todos los meses surgen nuevas publicaciones escritas, artículos digitales y comunidades en la web que tratan sobre esta disciplina. Además, al tratarse de un campo relacionado con la fase de diseño del software, éste es independiente del lenguaje de programación empleado. Los patrones de diseño pueden ser aplicados en lenguajes tan dispares como Java, C++, PHP, Visual Basic, C#, etc. Un ejemplo de la importancia que están tomando los patrones de diseño de software lo representa el hecho de que la metodología de desarrollo METRICA 3, de la Administra- ción General del Estado, incorpora una tarea dedicada a la identificación de patrones (DSI 2.2: Identificación de Mecanismos Genéricos de Diseño). En esta entrega de la serie veremos qué son los patrones de diseño y cuáles son los patrones de diseño básicos, patrones que aparecen con una gran frecuencia en la práctica. La presentación de cada patrón irá acompañado de una explica- ción teórica y de una visión práctica, en la que se verá su aplicación con distintos lenguajes de programación, lo que nos permitirá apreciar mejor su potencial. Patrones de diseño: concepto y disciplina Los patrones de diseño de software son solucio- nes reutilizables a problemas recurrentes que aparecen durante el proceso de diseño de soft- ware orientado a objetos. ¿Por qué surgen los patrones de diseño? Por la necesidad de transmitir la experiencia. Lo que diferencia a un programador brillante y experto de un programador igualmente brillante pero inexperto es la experiencia. Conforme un programador gana experiencia, éste reconoce el parecido entre los nuevos problemas que van surgiendo y los problemas que ya ha resuelto con anterioridad. Incluso cuando tiene más expe- riencia, es capaz de reconocer que las soluciones a estos problemas siguen patrones recurrentes. Con el conocimiento de estos patrones, los pro- gramadores expertos son capaces de identificar las situaciones en las que éstos tienen aplica- ción, y utilizarlos sin tener que detenerse para analizar el problema y vislumbrar diferentes estrategias de resolución. No obstante, que un programador haya descu- bierto un determinado patrón no implica que sea capaz de expresar su conocimiento a otros pro- gramadores. Aquí es donde aparece la disciplina de los patrones de diseño. Esta disciplina esta- blece una especie de especificación para docu- mentar los patrones de diseño de software orientado a objetos. Según esta especificación, todo patrón de diseño debe ir acompañado de: Nombre del patrón: Gracias a éste nombre podremos identificar al patrón y referirnos al mismo cuando discutamos con otros diseña- dores durante la fase de diseño. Sinopsis: Breve resumen que nos indica la esencia de la solución proporcionada por el patrón. Es de gran utilidad para los progra- madores expertos que no conocen el nombre del patrón. De esta forma, se les indica lo que éste hace. Contexto: Descripción detallada del problema recurrente que el patrón viene a solucionar. Solución: Contiene una descripción detallada del patrón, y viene acompañada de un diagra- ma de clases UML que refleja gráficamente esta solución. Ejemplo de aplicación: La descripción del patrón siempre será más rica si va acompaña- da de un ejemplo pràctico. No obstante, a lo largo de esta serie de artículos no emplearemos este formato de documenta- ción, que, aunque exhaustivo, podría resultar difícil de seguir. 52 A lo largo de esta serie de artículos haremos un repaso de los principales patrones de diseño de software y veremos cómo llevar a cabo su implementación con los lenguajes de programación más populares. ÁLVARO ZABALA ORDÓÑEZ DISEÑO Patrones de diseño: un curso práctico (I) Patrones de diseño: un curso práctico (I)

Upload: mauricio-solar

Post on 28-Dec-2015

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Patrones de Diseño Un Curso Practico 1

SOLO PROGRAMADORES

Introducción

El movimiento de los patrones de diseño seencuentra actualmente en auge. Todos losmeses surgen nuevas publicaciones escritas,artículos digitales y comunidades en la webque tratan sobre esta disciplina. Además, altratarse de un campo relacionado con la fasede diseño del software, éste es independientedel lenguaje de programación empleado. Lospatrones de diseño pueden ser aplicados enlenguajes tan dispares como Java, C++, PHP,Visual Basic, C#, etc.Un ejemplo de la importancia que estántomando los patrones de diseño de softwarelo representa el hecho de que la metodologíade desarrollo METRICA 3, de la Administra-ción General del Estado, incorpora una tareadedicada a la identificación de patrones (DSI2.2: Identificación de Mecanismos Genéricosde Diseño).En esta entrega de la serie veremos qué son lospatrones de diseño y cuáles son los patrones dediseño básicos, patrones que aparecen con unagran frecuencia en la práctica. La presentaciónde cada patrón irá acompañado de una explica-ción teórica y de una visión práctica, en la que severá su aplicación con distintos lenguajes deprogramación, lo que nos permitirá apreciarmejor su potencial.

Patrones de diseño: concepto y disciplina

Los patrones de diseño de software son solucio-nes reutilizables a problemas recurrentes queaparecen durante el proceso de diseño de soft-ware orientado a objetos.

¿Por qué surgen los patrones de diseño? Por lanecesidad de transmitir la experiencia.Lo que diferencia a un programador brillante yexperto de un programador igualmente brillantepero inexperto es la experiencia. Conforme unprogramador gana experiencia, éste reconoce elparecido entre los nuevos problemas que vansurgiendo y los problemas que ya ha resuelto conanterioridad. Incluso cuando tiene más expe-riencia, es capaz de reconocer que las solucionesa estos problemas siguen patrones recurrentes. Con el conocimiento de estos patrones, los pro-gramadores expertos son capaces de identificarlas situaciones en las que éstos tienen aplica-ción, y utilizarlos sin tener que detenerse paraanalizar el problema y vislumbrar diferentesestrategias de resolución.No obstante, que un programador haya descu-bierto un determinado patrón no implica que seacapaz de expresar su conocimiento a otros pro-gramadores. Aquí es donde aparece la disciplinade los patrones de diseño. Esta disciplina esta-blece una especie de especificación para docu-mentar los patrones de diseño de softwareorientado a objetos. Según esta especificación,todo patrón de diseño debe ir acompañado de:

Nombre del patrón: Gracias a éste nombrepodremos identificar al patrón y referirnos almismo cuando discutamos con otros diseña-dores durante la fase de diseño.Sinopsis: Breve resumen que nos indica laesencia de la solución proporcionada por elpatrón. Es de gran utilidad para los progra-madores expertos que no conocen el nombredel patrón. De esta forma, se les indica lo queéste hace.Contexto: Descripción detallada del problemarecurrente que el patrón viene a solucionar.Solución: Contiene una descripción detalladadel patrón, y viene acompañada de un diagra-ma de clases UML que refleja gráficamenteesta solución.Ejemplo de aplicación: La descripción delpatrón siempre será más rica si va acompaña-da de un ejemplo pràctico.

No obstante, a lo largo de esta serie de artículosno emplearemos este formato de documenta-ción, que, aunque exhaustivo, podría resultardifícil de seguir.

52

A lo largo de esta serie de artículosharemos un repaso de los principalespatrones de diseño de software yveremos cómo llevar a cabo suimplementación con los lenguajes deprogramación más populares.

ÁLVARO ZABALA ORDÓÑEZ

DISEÑO

Patrones de diseño:un curso práctico (I)Patrones de diseño:un curso práctico (I)

Page 2: Patrones de Diseño Un Curso Practico 1

SOLO PROGRAMADORES

Los orígenes de los patrones de diseño

Antes de entrar en materia, veremos deforma muy breve los orígenes de los patro-nes de diseño de software. El concepto de patrón de diseño procededel campo de la arquitectura. Los trabajosdel arquitecto Christopher Alexander(véase referencia [1] del cuadro "Bibliogra-fía recomendada"), publicados a finales dela década de los 70, postulaban la existen-cia de patrones repetitivos en las solucio-nes adoptadas en planeamiento urbanísticoy construcción. Estas ideas eran suscepti-bles de ser aplicadas a otras disciplinas,entre ellas, la de la Ingeniería del Software. Así, en el año 1987 los archiconocidosW.Cunningham y Kent Beck (padre de lametodología "Extreme Programming") uti-lizaron algunas de las ideas de Alexanderpara identificar una serie de patrones en laconstrucción de interfaces de usuario(véase referencia [2] del cuadro"Bibliografía recomendada"). Estos patro-nes se emplearon en el lenguaje SmallTalk(uno de los pioneros de los lenguajes orien-tados a objetos puros) y dieron lugar alconocidísimo patrón Modelo/Vista/Con-trolador. En el año 1994 Gamma, Helm, Vlissides yJhonson (grupo de autores conocido comoel Gof o "pandilla de los cuatro") publicaronel libro que es considerado la "biblia" de lospatrones de diseño (véase referencia [3] delcuadro "Bibliografía recomendada"). Estelibro popularizó la idea de los patrones dediseño e introdujo la clasificación de patro-nes de diseño más extendida en la actuali-dad. A partir de este momento, se produjola explosión del fenómeno de los patronesde diseño. Se han desarrollado patronesaplicables a diferentes niveles de la lógicade la aplicación, como persistencia, mensa-jería, presentación, etc. El último movimiento parece ser el de lospatrones para la creación de aplicacionesempresariales, que tratan de cubrir todoslos aspectos de un sistema empresarial.En este sentido cabe destacar los trabajosde Martin Fowler (véase referencia [4] delcuadro "Bibliografía recomendada"), o laspublicaciones de Sun (véase referencia [5]del cuadro "Bibliografía recomendada") yMicrosoft (véase referencia [6] del cuadro"Bibliografía recomendada") para mostrarcómo construir aplicaciones empresaria-

les con sus plataformas de desarrollo.Paralela-mente al concepto de patrón, haido surgiendo el concepto de "Antipa-trón". Se basa en la idea de que con fre-cuencia resulta más fácil aprender de loserrores, por lo que se trata de catalogarlos errores más frecuentes de análisis,diseño y programación.

Clasificación de los patrones de diseño

Los patrones de diseño varían tanto en sugranularidad como en su nivel de abstrac-ción. Puesto que existen numerosos patro-nes de diseño, éstos se clasifican en cate-gorías, lo que facilita su aprendizaje y per-mite referirse a patrones similares median-te la familia a la que pertenecen. En la obra del Gof (véase referencia [3] delcuadro "Bibliografía recomendada") se pro-ponen las siguientes categorías:

Patrones de creación: Esta categoríaagrupa a los patrones que proporcionanguías de cómo construir objetos, cuandosu creación implique la toma de unadecisión. Esta decisión puede ser básica-mente elegir qué subclase dentro de unajerarquía de herencia instanciar, y quéclase tiene la responsabilidad de su cre-aciónPatrones estructurales: Los patrones deesta categoría describen mecanismosgenéricos para organizar diferentes cla-ses de objetos entre sí.Patrones de comportamiento: Estospatrones se utilizan para organizar, ges-tionar y combinar el comportamiento dediferentes objetos.

A esta clasificación, Mark Grand en suobra "Patterns in Java" (véase referencia[7] del cuadro "Bibliografía recomenda-da") añade la categoría de "Patrones fun-damentales". Según este autor, esta cate-goría engloba a patrones que aparecencon mucha frecuencia en el resto depatrones, de mayor complejidad. Comenzaremos nuestro repaso de los prin-cipales patrones de diseño por dos patronesde esta categoría: el patrón Interfaz y elpatrón Delegación.

El patrón Interfaz

Este patrón prácticamente aparece en elresto de patrones de diseño que vamos aver a lo largo de esta serie de artículos, por

lo que con él nos vamos a detener un pocomás. Se utiliza cuando deseamos que unaclase que hace uso de los servicios propor-cionados por otras clases, permanezcaindependiente de estas.¿Qué ventajas obtenemos con ello? Reduceel acoplamiento entre clases, y evita la pro-pagación de cambios. ¿Y cómo podemosimplementar este patrón? A través de lautilización de interfaces. Una interfaz defi-ne un contrato que deben cumplir una seriede clases, independientemente de los deta-lles internos de implementación de cadauna de éstas. Se trata por tanto de un tipoespecial de herencia denominado "de inter-faz". Mediante la aplicación de este patrónde diseño, podemos independizar una clasede otra que le presta servicios, haciendoque no tenga una referencia a la clase queofrece el servicio, sino a la interfaz quedefine el contrato del servicio a prestar. ¿Cómo podemos implementar este patrónde diseño con algunos de los principaleslenguajes de programación? Java y C#, dos de los últimos en llegar, tie-nen una construcción de lenguaje denomi-nada interfaz. En C# podemos definir unainterfaz de la siguiente manera:interface Educado{

void diHola();

void diAdios();

}

Esta interfaz define un comportamiento,del que podrán heredar otras clases através de la herencia de interfaz. En ellistado 1 tenemos dos implementacionesde esta interfaz con C#. En dicho ejemplotenemos una interfaz "Educada", queobliga a que todas las clases que laimplementen tengan métodos de saludoy despedida, impresos por consola. Laclase EducadoIngles implementa estosmétodos en inglés, mientras que la claseEducadoCastellano en castellano. Lasinterfaces en Java son similares.Supongamos que tenemos una claseencargada de interactuar con el usuarioen un entorno de línea de comandos,saludándolo al iniciar la sesión y despi-diéndose al terminar. Podemos indepen-dizar nuestra clase del idioma empleadohaciendo que tenga una referencia a lainterfaz educado:

53

DISEÑOPatrones de diseño: un curso práctico (I)

Diagrama de clases UMLdel patrón Interfaz.

Page 3: Patrones de Diseño Un Curso Practico 1

SOLO PROGRAMADORES

class HaceUsoDeEducado{

private Educado educado;

}

En función del idioma seleccionado por el usua-rio, esta clase recibirá en su constructor unaimplementación u otra, sin necesidad de modifi-

car la clase que hace uso de los servicios ofreci-dos por esta interfaz. Es más: podemos seguirañadiendo soporte de nuevos idiomas, creandonuevas implementaciones de la interfaz.Otros lenguajes más antiguos, como C++ oVisual Basic carecen de interfaces. En su lugarofrecen otra construcción, las clases abstractas,también presentes en Java y C#.En C++ una clase es abstracta cuando tieneuno de sus métodos "virtual". El modificador"virtual" es similar al modificador "abstract"de Java y otros lenguajes. En C++ definiría-mos el contrato de nuestra interfaz con unaclase abstracta (que puede ser pura si todossus métodos son abstractos), y cada una delas implementaciones de la interfaz seríanclases que heredarían de ésta.Incluso las últimas versiones de Visual Basic(5 y 6), antes de su sustitución por VisualBasic .NET, permitían la definición de clasesabstractas. Para tal fin, había que crear unmódulo de clase con el asistente visual dellenguaje, y dar el valor "PublicNoCreatable" ala propiedad "Instancing" del módulo. Estohacía que no se pudiese utilizar ni el opera-dor "new" ni la función "CreateObject" paraobtener instancias de la clase. Un módulopodía implementar esta interfaz mediante eluso de la palabra reservada "implements".

El patrón Delegación

La delegación consiste en un medio de exten-der y reutilizar la funcionalidad de una clasemediante la creación de otra clase que se laproporcione. Todos los lenguajes orientados aobjetos proporcionan mecanismos paraimplementar este patrón, pues basta con aña-dir una nueva referencia a la clase que con-sume el servicio.La importancia del patrón Delegación radicaen que nos proporciona un mecanismo paradecidir cuándo debemos hacer que una claseherede de otra, o cuando añadirle una refe-rencia para utilizar sus servicios. En nuestroejemplo de la clase educada, parece claro quehay que utilizar delegación. Muchas veces ladecisión nos la da el sentido común (la reglade "es un"), mientras que otras veces habráque hacer un análisis del número de heren-cias posibles. En nuestro ejemplo, añadiendouna referencia a la interfaz "Educado" sólocrearemos una clase que consuma sus servi-cios, mientras que si optamos por el meca-nismo de la herencia, tendríamos que creardos subclases: una de EducadoIngles y otrade EducadoCastellano. Además, conformefuese creciendo el número de implementa-ciones de Educado, habría que ir aumentan-do el número de herencias. El listado 2 mues-tra la codificación en Java de este patrón.

54

DISEÑO

LISTADO 1 Patrón Interfaz en C#

using System;class EducadoIngles:Polite{

public void diHola(){Console.WriteLine("Hello!");

}public void diAdios(){

Console.WriteLine("Bye!");}}

using System;class EducadoCastellano:Polite{

public void diHola(){Console.WriteLine("Hola!");

}public void diAdios(){

Console.WriteLine("Adios!");}}

LISTADO 2 Patrón Delegado en Java

//Uso Correctopublic class ConDelegacion{

private Educado;}

//Uso Incorrectopublic class ConHerencia1 extends EducadoCastellano{}public class ConHerencia2 extends EducadoIngles{}

LISTADO 3 Patrón Singleton en C++

class Singleton { //Acceso a la instancia a través de un método estáticopublic: static Singleton* Instance(); //Constructor no publicoprotected: Singleton(); //unica instancia que puede existirprivate: static Singleton* _instance;

};

LISTADO 4 Patrón Singleton en VB.NET

Public Class Singleton' Unica instáncia del Singleton que puede existir (es shared)Private Shared FInstance As Singleton = Nothing' Constructor privadoPrivate Sub New()End Sub' Método estático que da acceso a la propiedadPublic Shared ReadOnly Property Instance()

GetIf (FInstance Is Nothing) Then

FInstance = New Singleton()End IfReturn FInstance

End GetEnd Property

End Class

Page 4: Patrones de Diseño Un Curso Practico 1

SOLO PROGRAMADORES

Patrones de creación: Singleton

Una vez introducidos dos de los patrones dediseño fundamentales, Interfaz y Delegación,veremos un patrón del tipo creacional muyfrecuente en la práctica: el patrón de diseñoSingleton.Este patrón se utiliza cuando queremos garan-tizar que, de una determinada clase, sólo exis-te una instancia. De esta forma, todos los obje-tos que hagan uso de esa clase utilizarán lamisma instancia. ¿Cuándo suele ser necesarioaplicar un Singleton? Cuando nos encontramoscon clases que deben encargarse de gestionarun recurso, bien sea externo (las conexiones auna base de datos, por ejemplo), bien sea inter-no (información de configuración global a nivelde sistema, información única para el contextode la aplicación, etc.)¿Cómo se implementa un Singleton? En primerlugar, se debe impedir que los clientes constru-yan instancias de la clase que se desea hacerSingleton. Para ello, lo normal es hacer su cons-tructor privado. Además, se debe hacer quedicha clase contenga una referencia estática a laúnica instancia de esa propia clase que puedeexistir. En el mundo de la orientación a objetos,se denomina estáticas a aquellas propiedades ymétodos que son comunes de una clase, y portanto compartidas por todas sus instancias. Porúltimo, se debe añadir al Singleton un métodopúblico y estático que devuelva la única referen-cia existente de esa clase.En el listado 3 vemos un ejemplo de cómoimplementar un Singleton en C++. Con estelenguaje resulta fácil su implementación, yaque permite crear métodos estáticos. El nuevolenguaje Visual Basic .NET, de la familia delenguajes .NET, también proporciona herra-mientas para implementar este patrón. En ellistado 4 vemos cómo implementar unSingleton en Visual Basic.NET.

Conclusiones

En esta primera entrega de la serie hemoshecho una introducción a los patrones dediseño de software, y hemos visto tres de losprincipales patrones: Interfaz, Delegación ySingleton, implementados con diferentes len-

guajes de programación. El próximo messeguiremos profundizando en éste prácticocampo de la ingeniería del software.

55

DISEÑOPatrones de diseño: un curso práctico (I)

Gestor de conexiones con el patrón Singleton.

En The Server Side podemos encontrar una sección dedicada a patrones de diseño(www.theserverside.com).

Bibliografía recomendada

[1] "A Pattern Language: Towns, Buildings, Construction." Christopher Alexander. 1977.[2] "Using Patterns Languages for Object-Oriented Programs". Ward Cunningham, Kent Beck. 1987[3] "Design Patterns: Elements of Reusable Object Oriented Software". Gamma, Helm, Vlissides y Jhonson. 1994[4] "Patterns Of Enterprise Application Architecture", Martin Fowler[5] "Java Blueprints" http://java.sun.com/blueprints/patterns/catalog.html[6] ".NET Enterprise Patterns". http://msdn.microsoft.com/practices/type/Patterns/Enterprise/[7] "Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML" Mark Grand.

Diagrama de clases UML del patrón Delegación