mercredi 27 octobre 2021

Decorator Pattern in Pascal/Lazarus

I am trying to implement the Decorator Pattern in a very simple example.

In this way, which should be the right one as far as "Decorator Interface" implements "Shape Interface" it does not work.

The line triangle := TGreenShapeDecorator.create(triangle); fails because tringle is of type IShape but not IShapeDecorator;

program project1;

{$mode objfpc}{$H+}

uses
   Classes, SysUtils;

type
   {Shape Interface}
   IShape = interface
      function draw():String;
   end;

   {Clase 1}
   TTriangle = class(TInterfacedObject, IShape)
      function draw():String;
   end;

   {Decorator Interface}
   IShapeDecorator = interface(IShape)
      property shape:IShape;
      function draw():String;
   end;

   {Decorator 1}
   TGreenShapeDecorator = class(TInterfacedObject, IShapeDecorator)
      shape : IShape;
      constructor create(shape_in:IShape);
      function draw():String;
   end;

function TTriangle.draw():String;
begin
   Result := 'Triangle';
end;

constructor TGreenShapeDecorator.Create(shape_in:IShape);
begin
   shape := shape_in;
end;

function TGreenShapeDecorator.draw():String;
begin
   Result := 'Green ' + shape.draw();
end;


var
   triangle : IShape;

begin
   // Triangle OBJECT
   triangle := TTriangle.Create;
   WriteLn(triangle.draw());

   // Green decorated triangle
   triangle := TGreenShapeDecorator.create(triangle);
   WriteLn(triangle.draw());

   ReadLn();
end. 

In this other way it works:

program project1;

{$mode objfpc}{$H+}

uses
   Classes, SysUtils;

type
   {Interfaz}
   IShape = interface
      function draw():String;
   end;

   {Clase 1}
   TTriangle = class(TInterfacedObject, IShape)
      function draw():String;
   end;

   {Decorator Interface}
   IShapeDecorator = interface
      property shape:IShape;
      function draw():String;
   end;

   {Decorator 1}
   TGreenShapeDecorator = class(TInterfacedObject, IShapeDecorator, IShape)
      shape : IShape;
      constructor create(shape_in:IShape);
      function draw():String;
   end;

function TTriangle.draw():String;
begin
   Result := 'Triangle';
end;

constructor TGreenShapeDecorator.Create(shape_in:IShape);
begin
   shape := shape_in;
end;

function TGreenShapeDecorator.draw():String;
begin
   Result := 'Green ' + shape.draw();
end;


var
   triangle : IShape;

begin
   // Triangle OBJECT
   triangle := TTriangle.Create;
   WriteLn(triangle.draw());

   // Green decorated triangle
   triangle := TGreenShapeDecorator.create(triangle);
   WriteLn(triangle.draw());

   ReadLn();
end.

Showing the result:
Triangle Green Triangle

Is it possible to do it in the first way and I am doing something wrong?, or is it not possible and the only way is the second one?

Thank you.

Aucun commentaire:

Enregistrer un commentaire