Monday, 21 September 2009

Implementando el patrón Adapter o Facade

En éste artículo os mostraré la utilización de éste Patrón -> Adapter o Facade que nos sirve para crear una clase que adapta otra clase. Con éste patrón transformamos una interfaz en otra, de ésta manera podemos crear una clase reusable que coopera con clases no relacionadas. Si os acordáis del diseño que propuse para la generación de TLine, implementé un abstract Factory para devolver diferentes tipos de líneas. Pues bien, ahora el problema que tengo es que necesito poder convertir una clase en otra y lo haré utilizando un patrón Adapter. Si observamos el diagrama UML que colgué hace unos días sobre la implementación de la jerarquía de TAbstractLine y sus descendientes tenemos:

Como podéis comprobar, la diversas factorías me permiten generar diferentes tipos de líneas. Mediante el estilo escogido, puedo crear las líneas con la configuración declarada en la factoría. El funcionamiento es bastante simple y me permite potenciar el polimorfismo entre líneas, ya que yo solo tengo un componente TAbstractLine que es el que se dibuja, y según la factoría se crea el tipo que se selecciona.

Ahora el problema reside en que deseo convertir un tipo de línea en otra. ¿Cómo lo hago?, en primer momento puede parecer que el diseño no es correcto, que no tendríamos que haber realizado una factoría y unir todas las líneas en una sola clase e ir intercambiando las propiedades para dibujar una cosa o la otra. Pero ésto no es así, cada clase está pensada para funcionar de ésta manera, y que en un futuro pueda crecer sin tocar mucho código. La solución para la implementación de la solución es simple, utilizando un patrón Adapter. Mediante éste patrón, lo que hago es coger un objeto de la clase TAbstractLine, ya sea del tipo TAbstractSimpleLine o TAbstractDottedDobleArrowLine, etc.

Mediante éste patrón, conseguiremos de una forma elegante, sin tener que tocar nada de la estructura creada anteriormente una clase que nos permite adaptar una clase hacia otra. De ésta manera cuando en la aplicación yo modifique el componente "Línea" y cambie las opciones de "Simple Arrow" a "Doble Arrow", lo que hará el adapter es cambiar las 2 clases y la OO mediante Polimorfismo se encargará de hacer el resto, ya que el evento "Draw" ya sabe desde donde se tiene que ejecutar.

El código de ejemplo de la clase es el siguiente:


//Adapted Class
type
TAdaptedLine = Class(TObject)
FObject : TAbstractLine;
procedure getProperties(const Abstract1: TAbstractLine; var Abstract2: TAbstractLine);
constructor Create(kind : TTypeLine; obj : TAbstractLine);
End;

function getAdaptedLine(kind : TTypeLine; obj : TAbstractLine) : TAbstractLine;

implementation

{ TAdaptedLine }

constructor TAdaptedLine.Create(kind : TTypeLine; obj: TAbstractLine);
var
factory : TLinesFactory;
begin
simple := TSimpleLinesFactory.Create(obj.FCanvas);
case kind of
SimpleLine: FObject := factory.GetLine;
SimpleArrowLine: FObject := factory.GetLineArrow;
SimpleDoubleArrowLine: FObject := factory.GetLineDoubleArrow;
DottedLine: FObject := factory.GetLine;
DottedArrowLine: FObject := factory.GetLineArrow;
DottedDoubleArrowLine: factory := dotted.GetLineDoubleArrow;
noLine: FObject := nil;
end;
getProperties(obj, FObject);
FreeAndNil(factory);
end;

function getAdaptedLine(kind : TTypeLine; obj : TAbstractLine) : TAbstractLine;
var
adapted : TAdaptedLine;
resObj : TAbstractLine;
begin
adapted := TAdaptedLine.Create(kind, obj);
resObj := adapted.FObject;
FreeAndNil(adapted);
result := resObj;
end;


  • Enlaces de interés:
The Adapter Pattern.
The Adapter and Facade Patterns.
Introduction to Designing Patterns with Delphi.

0 comments:

Post a Comment