Einzelnen Beitrag anzeigen

Dejan Vu
(Gast)

n/a Beiträge
 
#5

AW: dynamisch Klassenkonstruktor aufrufen

  Alt 25. Jul 2014, 08:08
Mit einer Classfactory geht das problemlos:
Delphi-Quellcode:
unit ClassFactory;

interface
uses
  SysUtils, Classes, Contnrs, SyncObjs;
Type
  TClassFactory = Class
  private
    fCS : TCriticalSection;
    fClasses : TClassList;
    fNames : TStringList;
  public
    Constructor Create;
    Destructor Destroy; Override;
    Procedure RegisterClass(Const aClassName : String; aClass : TClass);
    Function GetClass (Const aClassName : String) : TClass;
    Function GetInstance (Const aClassName : String) : TObject;
  End;

implementation

{ TClassFactory }

procedure TClassFactory.RegisterClass(const aClassName: String; aClass: TClass);
begin
  fCS.Enter;
  Try
    if fNames.IndexOf(aClassName)<>-1 then
      Raise exception.CreateFmt('Class %s already registered',[aClassname]);
    fNames.Add(aClassName);
    fClasses.Add(aClass);
  Finally
    fCS.Leave;
  End;
end;

constructor TClassFactory.Create;
begin
  fClasses := TClassList.Create;
  fNames := TStringList.Create;
  fNames.CaseSensitive := False;
  fCS := TCriticalSection.Create;
end;

destructor TClassFactory.Destroy;
begin
  fClasses.Free;
  fNames.Free;
  fCS.Free;
  inherited;
end;

function TClassFactory.GetClass(const aClassName: String): TClass;
Var
  i : Integer;

begin
  fCS.Enter;
  Try
    i := fNames.IndexOf(aClassName);
    if i=-1 then
      Raise Exception.CreateFmt('Class %s not registered',[aClassName])
    else
      Result := fClasses[i];
  Finally
    fCS.Leave;
  End;
end;

function TClassFactory.GetInstance(const aClassName: String): TObject;
Var
  c : TClass;

begin
  c := GetClass (aClassname);
  Result := C.Create;
end;

end.
Verwendung:
Delphi-Quellcode:
Var
  myClassFactory : TClassFactory;
  anApple, aPear : TObject;

begin
  myClassFactory := TClassFactory.Create;
  myClassFactory.RegisterClass('Apfel', TAppleClass);
  myClassFactory.RegisterClass('Birne', TPearClass);
  ...
  anApple := myClassFactory.GetInstance ('Apfel');
  aPear := myClassFactory.GetInstance('Birne');
...
Allerdings ist die Verwendung dieser Klassen irgendwie sinnlos, denn Du kennst ja die konkrete Schnittstelle nicht, weswegen der Zusatz von Hoika so wichtig ist.
Um solche Klasse aber verwenden zu können, muss entweder mit Interfaces oder mit einer gemeinsamen Basisklasse gearbeitet werden.
Das o.g. Pattern (die class factory) sollte man also für eine konkrete Basisklasse (oder noch besser: Interface) erstellen. Das geht über Generics sehr elegant.
  Mit Zitat antworten Zitat