Einzelnen Beitrag anzeigen

Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.542 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Austausch von Funktionalität , Interfaces ?

  Alt 22. Jan 2017, 13:05
Ein Minimalbeispiel (die "Factory" hier ist sehr simpel und unflexibel, soll aber auch nur das Prinzip verdeutlichen). Nehmen wir folgendes sehr simple Interface:
Delphi-Quellcode:
unit TierIntf;

interface

type
  ITier = interface
    ['{443BCADC-CD02-4A2A-BB55-A9AEBE03D37D}']
    procedure GibLaut;
  end;

implementation

end.
Jetzt bauen wir uns 2 Klassen, die das Interface implementieren (der Einfachheit halber in derselben Unit):
Delphi-Quellcode:
unit TierClasses;

interface

uses
  Dialogs, TierIntf;

type
  THund = class(TInterfacedObject, ITier)
  public
    procedure GibLaut;
  end;

  TKatze = class(TInterfacedObject, ITier)
  public
    procedure GibLaut;
  end;

implementation

{ THund }

procedure THund.GibLaut;
begin
  ShowMessage('Wuff');
end;

{ TKatze }

procedure TKatze.GibLaut;
begin
  ShowMessage('Miau');
end;

end.
Nun eine Klassenfabrik (einen Singleton), die uns je nach Bedingung die eine oder andere Klasse instanziert.
Delphi-Quellcode:
unit TierFactory;

interface

uses
  TierIntf, TierClasses;

type
  TTierFactory = class abstract
  public
    class function GetTier(IstHund: Boolean): ITier; static;
  end;

implementation

{ TTierFactory }

class function TTierFactory.GetTier(IstHund: Boolean): ITier;
begin
  if IstHund then
    Result := THund.Create
  else
    Result := TKatze.Create;
end;

end.
Das Frontend muss dann letztendlich nur noch das Interface und die Fabrik kennen.
Delphi-Quellcode:
procedure TFormTest.ButtonTierClick(Sender: TObject);
var
  Tier: ITier;
begin
  Tier := TTierFactory.GetTier(cbHund.Checked);
  Tier.GibLaut;
end;
Um wirklich flexibel zu werden, wäre die Bedingung aber kein Boolean, sondern ein Datentyp mit nahezu unendlich vielen möglichen Werten, z.B. ein String. Die Factory würde dann mindestens über 2 Klassenmethoden verfügen: Registrierung einer Klasse mit einem der möglichen Werte und Rückgabe einer Instanz anhand eines registrierten Wertes (oder auch nil, wenn kein registrierter Wert vorhanden). Um das Programm um weitere Tiere zu erweitern müssten sich deren Klassen lediglich an der Factory registrieren, an der Factory selbst und erst recht am Frontend sind keine Änderungen nötig.

[edit] Nachtrag: Bei der zuletzt angegebenen Vorgehensweise entfällt dann auch die Notwendigkeit, die Klassenunits in die uses-Klausel der Factory aufnehmen zu müssen. Allerdings ist das Instanzieren der entsprechenden Klasse dann nicht ganz trivial, ich habe das damals mit einer Menge RTTI realisieren müssen. [/edit]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen

Geändert von DeddyH (22. Jan 2017 um 13:13 Uhr)
  Mit Zitat antworten Zitat