Das Singleton – Ein Muster zum streiten?
Erstellt von Delphi400 am Sonntag 28. September 2008
Das Singleton soll sicher stellen, das es von einer Klasse zur Programmlaufzeit nur eine Instanz gibt. Ich persönlich nutze es zum Beispiel als Fehlerprotokollobjekt oder um eine Datenbankverbindung vorrätig zu halten.
Manche Entwickler sind der Meinung, das das Singleton schlechter Programmierstil sei, ein Hinweis auf Designschwächen. Ich sehe das anders. Es gibt nun mal manchmal die Notwendigkeit, dass man nur eine Instanz von einem Objekt haben darf. Wenn dem so ist, dann ist dass Singleton die beste Lösung.
Der grundsätzliche Lösungsansatz ist folgender:
- Der Constructor wird als private deklariert, damit von dem Objekt nicht mehr „von Außen“ eine Instanz erstellt werden kann.
- Dafür wird eine Methode GetInstance eingeführt, welche bei Bedarf (also beim ersten Aufruf) das Objekt erstellt und zurück gibt. Existiert bereits diese Instanz, wird sie lediglich zur Verfügung gestellt.
Hier ein Beispiel:
{ *********************************************************************** }
{ }
{ Delphi Entwursmustersammlung -- Singleton }
{ }
{ Autor: Thomas Gröschke }
{ Erstellt: 23.09.2008 }
{ }
{ *********************************************************************** }
unit Unit1;
interface
type
TSingleton = class(TObject)
protected
Counter: Integer;
constructor Create;
class var FInstance: TSingleton;
public
class function GetInstance: TSingleton;
procedure HalloWorld;
end;
implementation
uses SysUtils, Dialogs;
{
********************************** TSingleton **********************************
}
constructor TSingleton.Create;
begin
Counter := 0;
inherited;
end;
class function TSingleton.GetInstance: TSingleton;
begin
If FInstance = nil then
begin
FInstance := TSingleton.Create();
end;
Result := FInstance;
end;
procedure TSingleton.HalloWorld;
begin
inc(Counter);
ShowMessage('Hallo Welt! Das ist der Aufruf #' + IntToStr(Counter) + '.');
end;
end.
Testen zum Beispiel mit zwei Buttons auf einem Formular:
procedure TForm1.Button1Click(Sender: TObject);
var
FObj : TSingleton;
begin
FObj := TSingleton.GetInstance;
FObj.HalloWorld;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
TSingleton.GetInstance.HalloWorld;
end;
Anzumerken ist noch, dass dieser Ansatz nicht Threadsicher ist. Da ich noch nie mit Threads gearbeitet habe und ich deswegen von dem Thema keine Ahnung habe, lass ich es an dieser Stelle so stehen.
Weblinks: