Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Designfrage zu Klassen- und Instanzproperties (https://www.delphipraxis.net/208100-designfrage-zu-klassen-und-instanzproperties.html)

DeddyH 9. Jun 2021 12:03

Designfrage zu Klassen- und Instanzproperties
 
Ich hätte für eine Konfigurationsklasse gern die Möglichkeit, eine sagen wir mal initiale global verfügbare Instanz anzulegen als auch eine (temporäre) lokale. Meine bisherige Umsetzung:
Delphi-Quellcode:
type
  TMyConfig = class
  strict private
    class var FInstance: TMyConfig;
    class function GetInstance: TMyConfig; static;
    class destructor ClassDestroy;
  private
    FFeld: integer;
  public
    property Feld: integer read FFeld write FFeld;
    class property Instance: TMyConfig read GetInstance;
  end;

...

class function TMyConfig.GetInstance: TMyConfig;
begin
  if not Assigned(FInstance) then
    FInstance := TMyConfig.Create;
  Result := FInstance;
end;

class destructor TMyConfig.ClassDestroy;
begin
  FInstance.Free;
end;
Meine Frage: ist das ein gangbarer Weg, oder baue ich mir hier ein Anti-Pattern, das mir früher oder später um die Ohren fliegt?
Danke fürs Lesen

Der schöne Günther 9. Jun 2021 12:44

AW: Designfrage zu Klassen- und Instanzproperties
 
Das nennt sich „Singleton“. Such mal danach, einmal tief Luft holen und dann lesen.

DeddyH 9. Jun 2021 12:46

AW: Designfrage zu Klassen- und Instanzproperties
 
Danke, das ist mir bekannt, auch, dass das oft als verpönt angesehen wird. Ich nutze es aber gern als Alternative zu globalen Variablen.

Uwe Raabe 9. Jun 2021 13:08

AW: Designfrage zu Klassen- und Instanzproperties
 
Wenn es wirklich nur eine Instanz für diese Klasse in deinem Programm geben soll, dann spricht m.M. nichts gegen deinen Ansatz. Die Alternative wäre, diese eine Instanz jeweils als Parameter oder anderweitig mitzugeben wo sie gebraucht wird. Das halte ich aber für völlig unpragmatisch und in vielen Fällen für kontraproduktiv.

Natürlich gibt es andere Ansätze, mit denen diese Singleton-Instanz vermieden werden kann, wobei in den meisten Fällen dann doch intern wieder nur eine Instanz vorgehalten wird, was ja auch eigentlich die Vorgabe in diesem Anwendungsfall ist. Jetzt irgendwelche Klimmzüge zu machen, um formal dem Singleton-Shaming zu entgehen, erscheint mir nicht wirklich sinnvoll.

Wenn du es etwas flexibler haben möchtest, dann implementiere eine Factory-Funktionalität, die du bei Bedarf anpassen kannst um ein anderes Verhalten für Tests oder als Mock zu ermöglichen.
Delphi-Quellcode:
type
  TMyConfigClass = class of TMyConfig;
  TMyConfig = class
  strict private
    class var FMyConfigClass: TMyConfigClass;
    class var FInstance: TMyConfig;
    class function GetInstance: TMyConfig; static;
    class destructor ClassDestroy;
  private
    FFeld: integer;
  public
    property Feld: integer read FFeld write FFeld;
    class property Instance: TMyConfig read GetInstance;
    class property MyConfigClass: TMyConfigClass read FMyConfigClass write FMyConfigClass;
  end;

class function TMyConfig.GetInstance: TMyConfig;
begin
  if not Assigned(FInstance) then begin
    if Assigned(FMyConfigClass) then
      FInstance := FMyConfigClass.Create
    else
      FInstance := TMyConfig.Create;
  end;
  Result := FInstance;
end;

class destructor TMyConfig.ClassDestroy;
begin
  FInstance.Free;
end;

DeddyH 9. Jun 2021 13:17

AW: Designfrage zu Klassen- und Instanzproperties
 
Danke, Uwe, so flexibel benötige ich das gar nicht. Mir geht es darum, dass es eine "Hauptinstanz" geben soll, auf die ich überall, wo sie benötigt wird, zugreifen kann. Will ich aber eine andere Konfiguration testen, ohne mir die Hauptinstanz zu zerstören, erzeuge ich einfach eine weitere, stelle sie entsprechend ein, schaue, ob sie so funktioniert und kann im Erfolgsfall dann in der Hauptinstanz die neuen Werte zuweisen. So war mein Denkansatz.

stahli 9. Jun 2021 13:29

AW: Designfrage zu Klassen- und Instanzproperties
 
Ich habe so etwas mal mit 2 globalen Variablen und einer Funktion realisiert:

Delphi-Quellcode:
globVarMain: TObject = nil;
globVarTmp: TObject = nil;

function MyVar: TObject;
begin
  if Assigned(globVarTmp) then
    Exit(globVarTmp);
  if not Assigned(globVarMain) then
    globVarMain := TObject.Create;
  Exit(globVarMain);
end;
Wenn globVarTmp etwas zugewiesen wird, wird die Instanz verwendet, sonst die Main-Variable.

himitsu 9. Jun 2021 15:53

AW: Designfrage zu Klassen- und Instanzproperties
 
Dann nimm doch einen Record
Delphi-Quellcode:
var
  MyConfig = record
    Feld: integer;
  end;
Delphi-Quellcode:
var
  MyConfig = record
  private
    FFeld: integer;
  public
    property Feld: integer read FFeld write FFeld;
  end;
Kannst den Typen auch einzeln deklarieren

und seit Delphi 10.4.2 gibt es aus für Records sowas Constructor/Destructor, bzw. Class Constructor/Class Destructor,
also Initialize/Finalize (Custom Managed Records)

oder direkt ALLES als Class
Delphi-Quellcode:
type
  MyConfig = class abstract
  strict private class var
    FFeld: integer;
  public
    class property Feld: integer read FFeld write FFeld;
  end;

Stevie 9. Jun 2021 18:43

AW: Designfrage zu Klassen- und Instanzproperties
 
Abgesehen davon, dass dein GetInstance nicht thread-safe ist, sieht das in Ordnung aus.
Wie bei so vielen Prinzipien, (Anti-)Patterns etc ist es wichtig zu verstehen, warum sie generell als gut/schlecht angesehen werden.

Dir muss halt klar sein, dass du durch ein TMyConfig.Instance in deinem konsumierenden Code dir sowieso eine hartcodierte Abhängigkeit einhandelst - wie "schlimm" das ist, kommt darauf an, was alles in TMyConfig steckt oder auch nicht. Da du aber mit dem class function Instance Ansatz daran gehst und nicht wie oft anders implementiert NewInstance etc überschreibst um auf Biegen und Brechen zu verhindern, dass irgendjemand jemals eine 2. Instanz davon erzeugt ist das imho weniger problematisch.

DeddyH 9. Jun 2021 20:23

AW: Designfrage zu Klassen- und Instanzproperties
 
Danke, dann lasse ich das jetzt so.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf