Texto para explicar con un ejemplo que es y cómo se aplica el patrón decorador
Añadir responsabilidades a un objeto de forma dinámica. Los decoradores proporcionan una alternativa flexible a la herencia para extender funcionalidad.
Los objetos participantes en este patrón son:
Su filosofía consiste en añadir responsabilidades de forma dinámica al objeto
Como podemos observar en el gráfico superior, la clase [DecoratorAbstrat] y la clase [Parrafo] que es la que queremos decorar, heredan, las dos, de la misma clase [DecoradorComponetAbstract]. Así, cada decorador es capaz de encapsular una instancia de cualquier objeto que herede del componente común, o lo que es lo mismo, puede encapsular o bien un componente concreto o bien, otro decorador.
La encapsulación puede ser iterativa, de modo que un componente concreto puede ser encapsulado por un decorador, que a su vez puede ser encapsulado por otro decorador… y así sucesivamente, añadiendo nueva funcionalidad en cada uno de los pasos. Resumiendo: el patrón Decorador sustituye la herencia por un proceso iterativo de composición.
El objeto con el que el objeto cliente interactuará será aquel que se encuentre en la capa más externa (en este caso, DecoratorC), que se encargará de acceder a los objetos contenidos e invocar su funcionalidad, que será devuelta a las capas exteriores.
Consecuencias
Con tal de que el patrón quede claro, voy a mostrar un pequeño ejemplo de código en el que utilizo este patrón.
El ejemplo que voy a desarrollar se trata de decorar una clase párrafo,. Una de las clases añade delante y detrás del párrafo unos caracteres "@" y la otra añade unos caracteres "*".
El ejemplo es deliberadamente simple, pero complicándolo solo un poco se pueden diseñar decoradores que, por ejemplo, añaden (o quitan) el salto de línea al final del párrafo, O bien, que pongan detrás de cada punto un salto de línea (si no existe), o bien, poner las marcas de párrafo HTML [<p>…. </p>], y cualquier otra cosa que se te ocurra.
''' <summary> ''' [Patron Decorador] la clase 'Component' 'abstract' ''' </summary> Public MustInherit Class DecoradorComponentAbstract ' Función que devolverá la clase [ConcreteComponent] que contiene el párrafo que estamos decorando ' Se declara como virtual para que pueda sustituirse en las clases derivadas Public MustOverride Function OperacionDecorador() As Parrafo End Class ''' <summary> ''' [Patron Decorador] la clase 'ConcreteComponent' ''' En este caso es una clase que contiene un [párrafo] que queremos decorar ''' </summary> Public Class Parrafo Inherits DecoradorComponentAbstract ' contiene el texto original recibido Public ReadOnly Property TextoOriginal As String ' contendrá el texto final decorado Public Property TextoDecorado As String ' constructor Public Sub New(Texto As String) MyBase.New TextoOriginal = Texto TextoDecorado = Texto End Sub Public Overrides Function OperacionDecorador() As Parrafo ' no hacer nada TextoDecorado = TextoOriginal Return Me End Function End Class '----------------------------------------------------------------- ''' <summary> ''' La clase 'Decorator' abstract ''' </summary> Public MustInherit Class DecoratorAbstract Inherits DecoradorComponentAbstract '----------------------------- ' Solo sirve a efectos de trazabilidad ' No tiene ninguna tarea especifica para la ejecución del código Friend Property Descripcion As String = "DecoratorAbstrat" '---------------------------------------------------------------------------------- ' Un decorador o contiene una clase [ConcreteComponent] --> una clase Párrafo ' o contiene una clase [ConcreteDecorator] que hereda de [DecoratorAbstrat] ' y tiene que conservar ambos valores diferentes porque hay que hacer cosas diferentes con cada una de ellas ' Ejemplo ' Dim c As New ConcreteComponent("Hola caracola") ' Dim d1 As New ConcreteDecoratorA(c) ' Dim d2 As New ConcreteDecoratorB(d1) ' Dim d3 As New ConcreteDecoratorC(d2) '------------------------------------------------------------------------- Protected _componenteConcretoEncapsulado As Parrafo = Nothing Protected _decoradorConcretoEncapsulado As DecoratorAbstract = Nothing ' Constructor que recibe el la clase [ConcreteComponent] que encapsulará el decorator Public Sub New(componenteEncapsulado As Parrafo) _componenteConcretoEncapsulado = componenteEncapsulado End Sub ' Constructor que recibe el la clase [ConcreteDecorator] que encapsulará el decorator Public Sub New(decoradorEncapsulado As DecoratorAbstract) _decoradorConcretoEncapsulado = decoradorEncapsulado End Sub ' la función Decorador Public Overrides Function OperacionDecorador() As Parrafo 'Trabajar con el COMPONENTE CONCRETO encapsulado If Not (_componenteConcretoEncapsulado Is Nothing) Then _componenteConcretoEncapsulado = _componenteConcretoEncapsulado.OperacionDecorador() End If 'Trabajar con el DECORADOR CONCRETO encapsulado If Not (_decoradorConcretoEncapsulado Is Nothing) Then _componenteConcretoEncapsulado = _decoradorConcretoEncapsulado.OperacionDecorador() End If 'Devuelve un COMPONENTE concreto (En este ejemplo, una clase parrafo) Return _componenteConcretoEncapsulado End Function End Class ''' <summary> ''' Una clase 'ConcreteDecorator' ''' Se encarga de decorar, de poner tres asteriscos delante y detrás del texto ''' </summary> Class ConcreteDecoratorA Inherits DecoratorAbstract ' Constructor que recibe el la clase [ConcreteComponent] que encapsulará el decorator Public Sub New(componente As Parrafo) MyBase.New(componente) MyBase.Descripcion = "ConcreteDecoratorA - componente" End Sub ' Constructor que recibe el la clase [ConcreteDecorator] que encapsulará el decorator Public Sub New(decoradorEncapsulado As DecoratorAbstract) MyBase.New(decoradorEncapsulado) MyBase.Descripcion = "ConcreteDecoratorA - Encapsulado" End Sub Public Overrides Function OperacionDecorador() As Parrafo _componenteConcretoEncapsulado = MyBase.OperacionDecorador() _componenteConcretoEncapsulado.TextoDecorado = "*** " & _componenteConcretoEncapsulado.TextoDecorado & " ***" Return _componenteConcretoEncapsulado End Function End Class ''' <summary> ''' Una clase 'ConcreteDecorator' ''' Se encarga de decorar, de poner tres 'arrobas' delante y detrás del texto ''' </summary> Class ConcreteDecoratorB Inherits DecoratorAbstract ' Constructor que recibe el la clase [ConcreteComponent] que encapsulará el decorator Public Sub New(componente As Parrafo) MyBase.New(componente) MyBase.Descripcion = "ConcreteDecoratorB - componente" End Sub ' Constructor que recibe el la clase [ConcreteDecorator] que encapsulará el decorator Public Sub New(concreteDecorator As DecoratorAbstract) MyBase.New(concreteDecorator) MyBase.Descripcion = "ConcreteDecoratorB - Encapsulado" End Sub Public Overrides Function OperacionDecorador() As Parrafo _componenteConcretoEncapsulado = MyBase.OperacionDecorador() _componenteConcretoEncapsulado.TextoDecorado = " @@@ " & _componenteConcretoEncapsulado.TextoDecorado & " @@@ " Return _componenteConcretoEncapsulado End Function End Class
''' <summary> ''' Clase de pruebas del patron de diseño 'Decorador' ''' Decorator Design Pattern. ''' </summary> Class ConsoleStringDecoratorPrueba ''' <summary> ''' Entry point into console application. ''' </summary> Public Shared Sub Main() ' Create ConcreteComponent and two Decorators Dim c As New Parrafo("En un lugar de la Mancha") Dim d1 As New ConcreteDecoratorA(c) Dim d2 As New ConcreteDecoratorB(d1) ' ejecutar los decoradores d2.OperacionDecorador() 'mostrar el resultado Console.Write(c.TextoDecorado) ' esperar hasta que se pulse una tecla Console.ReadKey() End Sub End Class
y una imagen del resultado
© 1997 - - La Güeb de Joaquín | |||||
Joaquín Medina Serrano
|
|||||
|
Codificación | |
Fecha de creación | |
Última actualización | |
![]() |