|
¿Qué es un patrón de diseño de software? Los patrones de diseño de software nacen de sus homólogos patrones en la ingeniería civil o arquitectura de edificaciones, por este motivo quiero dar un ejemplo en este ámbito del cual se desprenderá luego con facilidad el concepto que representa un patrón, entonces veamos dicho ejemplo:
Si tenemos que construir una casa en un lugar en el cual nieva durante todo el año, una construcción tradicional tendría el problema de que el peso de la nieve acumulada en el techo horizontal y paralelo al piso, seria tan grande que la derrumbaría. Existen varias soluciones al problema pero la más optima y en la que seguramente estarán pensando en este momento es construir el techo de la casa con una gran pendiente para que la nieve caída se deslice por la misma y termine en el piso de forma que nunca se acumule sobre nuestro techo. Bueno esa solución en la que ustedes pensaron casi en forma automática es un patrón. Observemos además que la solución o patrón se repite infinidad de beses si observamos un pueblo donde nieva, lo que nos dice que la solución es reusable y comprobada. Ahora si, estamos en condiciones de definir formalmente un patrón de diseño de software diciendo que: Es una solución reusable y comprobada a un problema común en el desarrollo de software. Dada esta pequeña introducción veamos un ejemplo real en el ámbito del diseño de software el patrón constructor o builder pattern. Builder pattern Problema que resuelve: Como hacer para que un único proceso de construcción sea capas de crear diferentes productos para que dicho proceso nos abstraiga o oculte los detalles constructivos particulares de cada producto. Dado que las definiciones abstractas son más difíciles de comprender, llevaremos la definición anterior a un ejemplo concreto del mundo real para lograr una mayor claridad. Como hacer para que un único proceso de construcción, la secuencia de instrucciones (BuildTope(); BuildMedio(); BuildBase();), sea capas de crear diferentes productos como ser un cuadrado, un triangulo o un rectángulo, para que dicho proceso nos abstraiga o oculte los detalles constructivos particulares de cada figura geométrica (producto). Solución: La solución la ofrece el patrón constructor o en ingles (builder pattern), el mismo esta conformado por una clase directora (DibujanteDirector) que es la responsable del proceso de construcción, es en ella donde se encuentra la secuencia de comandos BuildTope(); BuildMedio(); BuildBase(); esta clase opera utilizando una clase abstracta (GraphicBuilder), en la cual se encuentran definidos los prototipos o firmas de los métodos BuildTope(); BuildMedio(); BuildBase(); pero no su implementación, dicha implementación es responsabilidad de cada constructor o builder concreto, en nuestro ejemplo son las clases CuadradoBuilder, TrianguloBuilder y RectanguloBuilder, estas clases encapsulan los detalles de implementación particulares de cada producto. El producto que queda construido después de la ejecución del único proceso de construcción es un objeto de la clase Grafico, podemos observar una relación de agregación que une las clases GraphicBuilder y la clase Grafico, esto se debe a que la clase GraphicBuilder esta compuesta por un objeto del tipo Grafico pero como la destrucción del objeto del tipo GraphicBuilder no implica destrucción del objeto Grafico se trata de una relación de agregación y no de composición, esto se simboliza con un diamante blanco del lado de la clase agregada. Diagrama de clases UML  (haga click para ampliar la imagen) Código fuente C# using System; using System.Collections.Generic; using System.Text; namespace Builder { classCliente { static void Main(string[] args) { CuadradoBuilder cuadradoBuilder = new CuadradoBuilder(); TrianguloBuilder trianguloBuilder = new TrianguloBuilder(); RectanguloBuilder rectanguloBuilder = new RectanguloBuilder(); DibujanteDirector dibujante = new DibujanteDirector(); dibujante.Dibujar(cuadradoBuilder); dibujante.Dibujar(trianguloBuilder); dibujante.Dibujar(rectanguloBuilder); cuadradoBuilder.GerGrafico().Show(); trianguloBuilder.GerGrafico().Show(); rectanguloBuilder.GerGrafico().Show(); Console.ReadKey(); } } public class DibujanteDirector { public void Dibujar(GraphicBuilder graphicBuilder) { graphicBuilder.BuildTope(); graphicBuilder.BuildMedio(); graphicBuilder.BuildBase(); } } public abstract class GraphicBuilder { public abstract void BuildTope(); public abstract void BuildMedio(); public abstract void BuildBase(); public Grafico GerGrafico() { return _grafico; } protected Grafico _grafico = newGrafico(); } public class CuadradoBuilder : GraphicBuilder { public override void BuildTope() { _grafico.Add("***"); } public override void BuildMedio() { _grafico.Add("* *"); } public override void BuildBase() { _grafico.Add("***"); } } public class TrianguloBuilder : GraphicBuilder { public override void BuildTope() { _grafico.Add(" * "); } public override void BuildMedio() { _grafico.Add(" *** "); } public override void BuildBase() { _grafico.Add("*****"); } } public class RectanguloBuilder : GraphicBuilder { public override void BuildTope() { _grafico.Add("*********"); } public override void BuildMedio() { _grafico.Add("* *"); } public override void BuildBase() { _grafico.Add("*********"); } } public class Grafico { public void Add(string dato) { _lineas.Add(dato); } public void Show() { foreach(string linea in _lineas) { Console.WriteLine(linea); } } private List<string> _lineas = newList<string>(); } } Resultado de la ejecución
|