Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Singleton in Delphi (https://www.delphipraxis.net/154671-singleton-delphi.html)

himitsu 21. Sep 2010 12:24

AW: Singleton in Delphi
 
OK, dann hier mal meine Gedanken zu einem SingletonPattern

die Basisklasse für Delphi 2009 und davor:
Delphi-Quellcode:
type
  TSingleton = class(TObject)
  private
    fIsInitialized: Boolean;
    fAllowFree:     Boolean;
    fIsSingelton:   Boolean;
    class var fSingleton: TSingleton;
    class procedure DoFree;
  protected
    property isInitialized: Boolean read fIsInitialized;  // to see whether the constructor must be executed (in contructors)
    property AllowFree:     Boolean read fAllowFree;      // to detect whether the object is released (in destructors)
    property isSingelton:   Boolean read fIsSingelton;    // note: not yet available in constructor
  public
    class function NewInstance: TObject; override;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    procedure FreeInstance; override;
  end;

class procedure TSingleton.DoFree;
begin
  if Assigned(fSingleton) then
    fSingleton.fAllowFree := True;
  fSingleton.Free;
end;

class function TSingleton.NewInstance: TObject;
begin
  if Assigned(fSingleton) then
    Result := fSingleton
  else
    Result := inherited;
end;

procedure TSingleton.AfterConstruction;
begin
  inherited;
  fIsSingelton := not Assigned(InterlockedCompareExchangePointer(Pointer(fSingleton), Pointer(Self), nil));
  fIsInitialized := True;
  if not fIsSingelton then fAllowFree := True;
end;

procedure TSingleton.BeforeDestruction;
begin
  if fAllowFree then
    inherited;
end;

procedure TSingleton.FreeInstance;
begin
  if fAllowFree then
    inherited;
end;

class destructor TSingleton.DestroyClass;
begin
  if Assigned(fSingleton) then
    fSingleton.fAllowFree := True;
  fSingleton.Free;
end;

initialization

finalization
  TSingleton.DoFree;

end.
die Basisklasse ab Delphi 2010 (die ältere Version geht aber auch noch):
Delphi-Quellcode:
type
  TSingleton = class(TObject)
  private
    fIsInitialized: Boolean;
    fAllowFree:     Boolean;
    fIsSingelton:   Boolean;
    class var fSingleton: TSingleton;
  protected
    property isInitialized: Boolean read fIsInitialized;  // to see whether the constructor must be executed (in contructors)
    property AllowFree:     Boolean read fAllowFree;      // to detect whether the object is released (in destructors)
    property isSingelton:   Boolean read fIsSingelton;    // note: not yet available in constructor
  public
    class function NewInstance: TObject; override;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    procedure FreeInstance; override;
    class destructor DestroyClass;
  end;

class function TSingleton.NewInstance: TObject;
begin
  if Assigned(fSingleton) then
    Result := fSingleton
  else
    Result := inherited;
end;

procedure TSingleton.AfterConstruction;
begin
  inherited;
  fIsSingelton := not Assigned(InterlockedCompareExchangePointer(Pointer(fSingleton), Pointer(Self), nil));
  fIsInitialized := True;
  if not fIsSingelton then fAllowFree := True;
end;

procedure TSingleton.BeforeDestruction;
begin
  if fAllowFree then
    inherited;
end;

procedure TSingleton.FreeInstance;
begin
  if fAllowFree then
    inherited;
end;

class destructor TSingleton.DestroyClass;
begin
  if Assigned(fSingleton) then
    fSingleton.fAllowFree := True;
  fSingleton.Free;
end;
und eine Beispielklasse:
Delphi-Quellcode:
type
  TMyClass = class(TSingleton)
    Value: String;
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyClass.Create;
begin
  if not isInitialized then
  begin
    inherited;
    ////////////////////

    ShowMessage('Ich wurde erstellt');

    ////////////////////
  end;
end;

destructor TMyClass.Destroy;
begin
  if AllowFree then
  begin
    ////////////////////

    //ShowMessage('ich werde jetzt freigegeben');
    // wird nicht mehr angezeigt, nachdem die VCL beendet wurde
    MessageBox(0, 'ich werde jetzt freigegeben', '', 0);

    ////////////////////
    inherited;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  S: TMyClass;
begin
  S := TMyClass.Create;
  S.Value := 'test';
  S.Free;

  S := TMyClass.Create;
  ShowMessage('mein Wert ist: ' + S.Value);
end;

Stevie 21. Sep 2010 12:57

AW: Singleton in Delphi
 
Wie schon erwähnt, immernoch das gleiche Problem, du musst eine Klasse, die du als Singleton benutzen willst, von TSingleton ableiten -> Abhängigkeit.
Du kannst keine beliebige (wie schon erwähnt, in Theorie, habs noch nicht mit mehr als TFoo und TBar getestet) Klassen in Singletons umwandeln, ich schon.

himitsu 21. Sep 2010 13:04

AW: Singleton in Delphi
 
Joar, das Singleton muß hier quasi an der Spitze stehen.
Leider bieten die Generics es nicht an, daß man damit die Basisklasse setzen kann.
Delphi-Quellcode:
TSingleton<Base: class> = class(Base)
  ...
end;
Du kannst es aber manuell selber machen, indem du TObjekt bei TSingleton abänderst.
Man könnte ja zumindestens eine Codevorlage daraus basteln.

Stevie 21. Sep 2010 13:21

AW: Singleton in Delphi
 
Zitat:

Zitat von himitsu (Beitrag 1050950)
Joar, das Singleton muß hier quasi an der Spitze stehen.
Leider bieten die Generics es nicht an, daß man damit die Basisklasse setzen kann.
Delphi-Quellcode:
TSingleton<Base: class> = class(Base)
  ...
end;
Du kannst es aber manuell selber machen, indem du TObjekt bei TSingleton abänderst.
Man könnte ja zumindestens eine Codevorlage daraus basteln.

Das ist doch genau das, was ich gemacht habe :gruebel:

himitsu 21. Sep 2010 13:26

AW: Singleton in Delphi
 
Zitat:

Zitat von Stevie (Beitrag 1050953)
Das ist doch genau das, was ich gemacht habe :gruebel:

Nein,

du hast quasi dieses
Delphi-Quellcode:
TSingleton<T> = class
  ...
  class property Instance: T read FInstance;
  ...
end;
gemacht, aber nicht jenes
Delphi-Quellcode:
TSingleton<T> = class<T>
  ...
end;
.


Also du hast eine Klasse in einer anderen Klasse/Record verpackt.
(wobei man dort eben auch noch aufpassen muß, daß man dieses gekapselte Objekt nicht extern freigibt)

Bei mir und wenn dieser Generic so ginge, würde das Objekt von dem Singleton abgeleitet und hätte dann in sich selber diese Funktionalität aufgenommen.

Oder man leitet den Singleton von der gewünschten Klasse ab und baut dieses Verhalten dann nachträglich ein (hierfür muß man aber zusätzlich noch alle Konstruktoren überschreiben/verdecken und mit Konstrukoren besetzen, welche der dem vorhandenen TSingleton.Create entsprechen).

Stevie 21. Sep 2010 14:02

AW: Singleton in Delphi
 
Zitat:

Zitat von himitsu (Beitrag 1050954)
Also du hast eine Klasse in einer anderen Klasse/Record verpackt.
(wobei man dort eben auch noch aufpassen muß, daß man dieses gekapselte Objekt nicht extern freigibt)

Und genau das hab ich ja verhindert. Ich habe quasi soweit mit Delphi möglich
Delphi-Quellcode:
TSingleton<T> = class<T>
  ...
end;
gebaut, denn genau das, was den Singleton ausmacht ist, nämlich, dass nur einmal eine Instanz erzeugt wird und verhindert wird, diese freizugeben, ist gegeben.

himitsu 21. Sep 2010 15:05

AW: Singleton in Delphi
 
Irgendwie wird in meinem D2010 dein Class-Constructor nicht aufgerufen.
Folglich bleibt die Instanz immer nil und beim Zugriff darauf knallt es dann immer.

Stevie 21. Sep 2010 15:48

AW: Singleton in Delphi
 
Zitat:

Zitat von himitsu (Beitrag 1050996)
Irgendwie wird in meinem D2010 dein Class-Constructor nicht aufgerufen.
Folglich bleibt die Instanz immer nil und beim Zugriff darauf knallt es dann immer.

Zeig ma bitte, wie du den Singleton erstellt hast.

himitsu 21. Sep 2010 15:56

AW: Singleton in Delphi
 
Erst hatte ich was Eigenes versucht, aber auch mit deinem Beispielcode aus'm Post #1 (mit TStringList statt TFoo) geht's nicht.

Stevie 21. Sep 2010 16:05

AW: Singleton in Delphi
 
Zitat:

Zitat von himitsu (Beitrag 1051011)
Erst hatte ich was Eigenes versucht, aber auch mit deinem Beispielcode aus'm Post #1 (mit TStringList statt TFoo) geht's nicht.

Konsolenanwendung? Hab gerade gemerkt, dass dort was schief läuft, schau ich mir nachher mal zu Hause an. In ner VCL Forms Anwendung läufts bei mir.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:14 Uhr.
Seite 2 von 3     12 3      

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