Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   Delphi [Tutorial] Singletons in Delphi (https://www.delphipraxis.net/146936-%5Btutorial%5D-singletons-delphi.html)

MisterNiceGuy 29. Jan 2010 17:27


[Tutorial] Singletons in Delphi
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo alle miteinander,

ich habe heute mal ein kurzes Tutorial über Singletons in Delphi geschrieben.
Das ganze umfasst eine kurze Erklärung über den Begriff "Singleton" und eine
Beispielimplementierung. Ich habe versucht das ganze so einfach wie möglich zu
halten :)

Runterladen kann man das ganze hier und auf meinem Blog: klick

Aphton 29. Jan 2010 18:27

Re: [Tutorial] Singletons in Delphi
 
Kurz und würzig, bravo und danke!

MfG

freak4fun 29. Jan 2010 18:30

Re: [Tutorial] Singletons in Delphi
 
Müsste das auf deiner Seite nicht download (pdf, 17kb) statt download (pfd, 17kb) heißen? :stupid:

Teekeks 29. Jan 2010 19:36

Re: [Tutorial] Singletons in Delphi
 
Ich schließe mich da voll und ganz Aphton an.

MisterNiceGuy 29. Jan 2010 19:47

Re: [Tutorial] Singletons in Delphi
 
Upala, stimmt, pdf, danke :)

Stoney 29. Jan 2010 19:55

Re: [Tutorial] Singletons in Delphi
 
Gutes Tutorial. :)

Zwei Anmerkungen hätte ich allerdings noch:
Delphi-Quellcode:
var g_BK:Tbundeskanzler;
sollte besser nach "implementation" deklariert werden, damit der Entwickler nicht versehentlich direkt auf g_BK zugreifen kann.

Der Delphi-Compiler schreibt zurecht eine Warnung aus, dass der Konstruktor nicht in private deklariert werden sollte. Am besten solle es so aussehen:
Delphi-Quellcode:
{$WARNINGS OFF}
constructor Create;
{$WARNINGS ON}

MisterNiceGuy 29. Jan 2010 20:14

Re: [Tutorial] Singletons in Delphi
 
Oh okay, die Warnung bekommen ich in D7 nicht :) Danke für die Tips, werd's noch einarbeiten!

scrat1979 29. Jan 2010 21:26

Re: [Tutorial] Singletons in Delphi
 
Das Tutorial kommt wie gerufen für mich :) Danke Dir...

SCRaT

P.S.: Habe im Netz im Rahmen meiner Recherchen noch einen Singleton gefunden, in dem die Anzahl der Instanzen noch gespeichert wird, und wenn die letzte Instanz
(d.h. InstanceCount = 0), dann wird der Speicher komplett freigegeben. Fand ich auch eine "schöne" Sache...

mr2 29. Jan 2010 21:52

Re: [Tutorial] Singletons in Delphi
 
Hallo,

folgendes ist mir aufgefallen:

Zitat:

Delphi-Quellcode:
var BK:TBundeskanzer;
begin
  // BK muss natürlich zuvor noch initialisiert werden
  TBundeskanzer.getInstance; // Funktion steht zur Verfügung
  BK.getInstance; // Funktion wird nicht gefunden
end;

Das ist so nicht korrekt, class functions (& procedures) können in Delphi sehr wohl auch auf einer Instanz aufgerufen werden.

Zitat:

Delphi-Quellcode:
Destructor TBundeskanzler.destroy;
begin
  if g_BK = self then
    g_BK := nil;
  inherited destroy;
end;

Die Prüfung auf "g_BK = Self" kannst Du Dir sparen (es ist ja ein Singleton).
Statt dessen finde ich es sinnvoller im Destruktor eine Exception ausgelöst werden, damit niemand (aus Versehen oder absichtlich) die Singleton-Instanz zerstört.

Delphi-Quellcode:
destructor TBundeskanzler.destroy;
begin
  raise Exception.Create('Singleton darf nicht zerstört werden!');
end;
Die Methode getInstance sollte nach Möglichkeit Threadsicher gestaltet werden, damit beim gleichzeitigen Zugriff durch zwei Threads beide die selbe Instanz erhalten:

Delphi-Quellcode:
Function TBundeskanzer.getInstance:TBundeskanzler;
begin
  if (g_BK = nil) // statt TBundeskanzler.create reicht auch nur Create
  then InterlockedCompareExchange(g_BK, Create, nil);
  Result := g_BK;
end;
mr2

TBx 30. Jan 2010 04:23

Re: [Tutorial] Singletons in Delphi
 
Zitat:

Zitat von scrat1979
Habe im Netz im Rahmen meiner Recherchen noch einen Singleton gefunden, in dem die Anzahl der Instanzen noch gespeichert wird, und wenn die letzte Instanz (d.h. InstanceCount = 0), dann wird der Speicher komplett freigegeben. Fand ich auch eine "schöne" Sache...

ähm, räusper ...

das widerspricht sich total. Von einem Singelton kann es nicht mehr als eine Instanz geben, sonst wäre es ja keines .....

stoxx 30. Jan 2010 05:58

Re: [Tutorial] Singletons in Delphi
 
in neueren Delphi-Versionen würde man aber statt der Variablen in der Unit eine class var benutzen ..

Delphi-Quellcode:
TBundeskanzler = class
private
  class var Bundeskanzler : TBundeskanzler;

end
;

Meflin 30. Jan 2010 12:35

Re: [Tutorial] Singletons in Delphi
 
Zitat:

Zitat von TBx
ähm, räusper ...
das widerspricht sich total. Von einem Singelton kann es nicht mehr als eine Instanz geben, sonst wäre es ja keines .....

Der Witz am Singleton ist doch, dass man es eben doch leicht so abändern kann, dass man mehrer Instanzen zulassen kann. Ansonsten könnte man ja auch einfach alles klassenseitig implementieren.

sx2008 30. Jan 2010 14:49

Re: [Tutorial] Singletons in Delphi
 
Singletons sollte man durchaus kritisch sehen :warn:
Letztendlich handelt es sich dabei um globale Objekte; also im Prinzip das Gleiche wie globale Variablen.
Globale Variablen und Singletons machen uns Programmierer das Leben schwer, weil sie unangenehme Seiteneffekte hervorrufen.

Wer Englisch versteht sollte sich unbedingt mal dieses Video The Clean Code Talks - "Global State and Singletons" auschauen.
Es könnte die Meinung über Singletons grundlegend ändern...

alzaimar 30. Jan 2010 15:42

Re: [Tutorial] Singletons in Delphi
 
Ich finde das Tutorial gut, aber besser wäre es, wenn es sich noch an die Styleguidelines bezüglich Nomenklatur halten würde.
Felder beginnen mit 'f', keine 'ungarische Notation' bzw. Verklausulierung des Datentyps, und Underscores sollten vermieden werden.

Zum Google-Video fällt mir nur ein, das es natürlich wichtig ist, auf die Gefahren hinzuweisen, die sich hinter solchen Praktiken verbergen, aber man muss schon die richtigen Schlüsse daraus ziehen.
Die Dogmen der 'modernen' Softwareentwicklung sind wirklich sinnvoll:
1. Globale Variablen sind böse. Mein Programm ist eine globale Variable, ebenso alle Formulare und Datenmodule.
2. Goto's sind böse. Mein Programm besteht letztendlich aus (fast) nichts anderem.
3. Singletons sind böse. Neben dem Programm verzichte ich damit auf Caches, Dictionaries, Logger, Drucker, Festplatten und Bildschirme etc.. Oh, und letztendlich auf den User.

Also ich weiss nicht. Ich LIEBE es, gegen Dogmen zu verstoßen. Und verdiene mein Geld damit. Allerdings auch nur deshalb, weil ich nicht inflatorisch gegen Dogmen verstoße.

Ach so, bei jedem Argument gehört ein :stupid: und ein :mrgreen: dahinter, :zwinker:

Zurück zum Tutorial: Ich würde folgenden Gegenvorschlag machen:
Delphi-Quellcode:
unit SingletonUnit;
interface
type
  TSingleton = class
  protected
  // Verbergen der dem Singleton-Prinzip widersprechenden Methoden, so kann man dann nicht mal 'aus Versehen'
  // ein Singleton freigeben.
    constructor Create;
    destructor Destroy;
    procedure Free;
  public
  // Es ist nur das sichtbar, was das Singleton kann
    procedure PublicMethod();
  end;

// Automatische 'Lazy initialization'
function Singleton: TSingleton;

implementation
var
  SingletonInstance: TSingleton;

function Singleton: TSingleton;
begin
  if SingletonInstance = nil then
    SingletonInstance := TSingleton.Create;
  Result := SingletonInstance;
end;

{ TSingleton }

constructor TSingleton.Create;
begin
  inherited;
end;

destructor TSingleton.Destroy;
begin
  inherited;
end;

procedure TSingleton.Free;
begin
  inherited Free;
end;

procedure TSingleton.PublicMethod;
begin
  // Do Something;
end;

initialization
  SingletonInstance := nil;
finalization
  SingletonInstance.Free;
end.

MisterNiceGuy 31. Jan 2010 01:31

Re: [Tutorial] Singletons in Delphi
 
Hi, danke für eure Hinweise :)

@mr2: InterlockedCompareExchange funktioniert nicht mit Create als 2. Parameter. Hast du das getestet?

schlecki 31. Jan 2010 13:39

Re: [Tutorial] Singletons in Delphi
 
Hallo,

nochmal zum Problem mit dem Konstruktor: Es kann nichts mehr versteckt werden, was bereits in einer Elternklasse veröffentlich wurde. Man kann dann zwar nicht genau diesen Konstruktor aufrufen, trotzdem ist es möglich, eine Instanz dieser Klasse zu erzeugen.

Besser ist es, wenn man soetwas macht:

Delphi-Quellcode:
TSingleton = class(TObject)
private
  constructor _Create();
public
  constructor Create();
end;

{...}

constructor TSingleton.Create();
begin
  raise Exception.Create('Use TSingleton.getInstance!');
end;

constructor TSingleton._Create();
begin
  inherited Create;
  {...}
end;
Auf diesem Weg ist es nicht mehr möglich, eine Instanz dieser Klasse ohne den eigenen Konstruktor zu erzeugen.

alzaimar 31. Jan 2010 16:23

Re: [Tutorial] Singletons in Delphi
 
Soweit ich das überschaue, bekommt man soetwas nicht bullet-proof hin, d.h. es ist immer möglich, das jemand mutwillig das Konzept unterminiert, z.B. durch Typecasting. Aber ich denke, darum muss man sich nicht kümmern, das ist imho etwas spitzfindig, denn wir entwickeln Klassen und Konzepte nicht für unsere Feinde, sondern Kollegen.

Es geht doch eher darum, das man ein Singleton nicht mehrfach instantiiert oder versehentlich freigibt, weil man das Konzept nicht begriffen hat, und nicht, das man es unter allen umständen verbietet. Dann würde ich -glaube ich- einen Sentinel schreiben, der alle Instanzen außer der ersten gnadenlos abschießt und den (End-)Benutzer mit einer entsprechenden Meldung verwirrt. Natürlich könnte man auch das wieder umgehen usw. Also, WTF.

schlecki 31. Jan 2010 16:34

Re: [Tutorial] Singletons in Delphi
 
Darum gehts hier doch gar nicht. Wenn man nicht weiß, dass es sich um ein Singleton handelt, bekommt man es auch nicht mit, wenn man es mal mit TSingleton.Create aufruft.
Bei mir kommt eben ein Hinweis, wie man die Klasse richtig verwendet. Auch unter Kollegen kann so ein Hinweis ganz nett sein, bevor man ev. stundenlang den Fehler sucht, warum die Konfiguration oder sowas nicht korrekt geschrieben wird.

Edith sagt:

Hast du eigentlich schon mal folgendes probiert?

Delphi-Quellcode:
type
  TSingleton = class(TObject)
  private
    constructor Create;
  end;
und dann in einer anderen Unit(!):
Delphi-Quellcode:
var
  s: TSingleton;
begin
  s := TSingleton.Create;
end;
Das kompiliert ganz wunderbar, nur der aufgerufene Konstruktor ist der von TObject. Wunderbar, was? Und das alles ganz ohne Typecast.

Und nochwas, ich versuche, meine Sachen immer so sicher wie möglich zu machen. Warum? Vielleicht habe ich ja eine Bibliothek oder Komponente erstellt, die ich mit Sourcecode weiterverteilen möchte. Und dann macht man es den Benutzern doch wesentlich einfacher, die eigene Arbeit korrekt zu verwenden.

alzaimar 1. Feb 2010 04:38

Re: [Tutorial] Singletons in Delphi
 
Echt? Ich hab nur in der Codevervollständigung keinen Vorschlag mehr für Create gefunden, glaub ich jedenfalls. :gruebel:
Wenn das gar nicht stimmt und nichts bringt, ist es natürlich für die Katz.

Kennst Du denn eine absolut saubere Implementierung eines Singletons in Delphi? Ich glaub, das geht gar nicht.
Delphi ist eben keine moderne Programmiersprache, in C# ist es mit einigen wenigen Zeilen Code getan.

schlecki 1. Feb 2010 06:59

Re: [Tutorial] Singletons in Delphi
 
Zitat:

Zitat von alzaimar
Kennst Du denn eine absolut saubere Implementierung eines Singletons in Delphi? Ich glaub, das geht gar nicht.
Delphi ist eben keine moderne Programmiersprache, in C# ist es mit einigen wenigen Zeilen Code getan.

Eine absolut saubere Implentierung kenn ich auch nicht. Aber im Normalfall reicht die Version mit der Exception im Create.

Stevie 1. Feb 2010 07:17

Re: [Tutorial] Singletons in Delphi
 
Sofern man Delphi 2010 zur Verfügung hat, finde ich diese Implementierung recht interessant.

mr2 1. Feb 2010 19:56

Re: [Tutorial] Singletons in Delphi
 
Das Create scheint nicht das Problem zu sein, eher der erste Parameter.

So geht es bei mir unter Delphi 6:
Delphi-Quellcode:
  InterlockedCompareExchange(Pointer(_Instance), Create, nil);
mr2


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:42 Uhr.

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