The so-called Singleton means that only one instance of a certain class can exist in the system. In reality, it is very common to have only one instance object. For example, the system configuration object can have only one,
For example, only one connection is allowed for TCP/IP connections on the same client and server. The following is a UML diagram of the singleton mode:
Implementation of Singleton Mode
So how can we ensure that there is only one class instance every moment in the system? This can be achieved through static variables. When getinstance is called, we can determine whether the static variable is nil,
If it is nil, it indicates that there are no instances of classes in the system, the object is constructed, and the class instance is assigned to the static variable. If it is not nil, the instance of the class corresponding to the static variable is directly returned.
In Java or C ++, variables in the class can be modified to static, indicating that the variable exists independently of the class instance. There is no similar keyword in Delphi, so it can only be
Defines the private variables of a unit to reference and Count class instances.
In addition, to prevent users from using class constructor to create multiple class instances in Java, you must change the access attribute of the constructor to private. However, in Delphi,
The compiler performs special processing on the protection level of the contructor. Even if the contructor method is set to private access, the compiler still sets the protection level of the contructor.
Do not change to public. Therefore, it is impossible to adjust the protection level of the constructor to prevent multiple instances from being generated in Delphi. Fortunately, the newinstance method is defined in the tobject base class,
This method is a class method. The magic System of the compiler calls this class method every time an object is constructed. By reloading this static method, you can control the constructor.
The following is the sample configuration code:
Tsingleconfig =Class(Tobject)
Private
Fconfigpath:
String;
Procedure
Setconfigpath (const value: string );
Public
ClassFunction
Getinstance (): tsingleconfig;
//System Configuration path
Property
Configpath: String read fconfigpath write setconfigpath;
//...Omitted
ClassFunction
Newinstance: tobject; override;
Procedure
Freeinstance; override;
End;
Implementation
VaR
Globalconfig: tsingleconfig = nil; // Private Static configuration object variable in the unit
{Tsingleconfig
}
Procedure
Tsingleconfig. freeinstance;
Begin
Inherited;
Globalconfig: = nil;
End;
Class Function
Tsingleconfig. getinstance: tsingleconfig;
Begin
If not
Assigned (globalconfig)Then
Globalconfig: = tsingleconfig. Create ();
Result: = globalconfig;
End;
Class Function
Tsingleconfig. newinstance: tobject;
Begin
If not
Assigned (globalconfig)Then
Globalconfig: = tsingleconfig (inherited newinstance );
Result: = globalconfig;
End;
Procedure
Tsingleconfig. setconfigpath (const value: string );
Begin
Fconfigpath: =
Value;
End;
Static class methodsGetInstanceThrough static variablesGlobalConfigDetermine the corresponding object firstGlobalConfigWhether the variable isnil
, IfnilIndicates that the instance of the object has not been initialized in the system. In this case, the private constructor is called to initialize the object and assign itGlobalConfig
Variable.nil, Returns the createdGlobalConfigObject. PassGlobalConfigTo ensure that the object instance is always only
One (note:GlobalConfigObject must be declared inImplementationPart, instead of declaring in the unitInterfaceIn this way, the variable is out of the Unit
The user is invisible, which can protect the variable from being mistakenly modified by the user ).
In addition, you may release an object after it is used.DelphiWhen an object is released, the variable corresponding to its instance is not automatically setnil
If you callGetInstanceAlthough the global object has been destroyedAssigned(GlobalConfig)Still returns true,
SoGetInstanceReturns an incorrect pointer, resulting inAVError. To avoid this situation, you can reloadFreeInstanceMethod.
It will always be called during releaseFreeInstanceAfter the object is releasedGlobalConfigResetnilYou can.
VCLSingleton in
InVCLThere are also many Singleton instances, such as the clipboard class.TClipboardClass, inClipbrd.pasThe Unit provides instance control technology similar to the above, but it is
FunctionClipboardTo return the unique instance of the clipboard,
function Clipboard:
TClipboard;
begin
if FClipboard = nil then
FClipboard := TClipboard.Create;
Result := FClipboard;
end;
Similarly, it also sets static variablesnil
destructor TClipboard.Destroy;
begin
if (FClipboard = Self) then
FClipboard := nil;
inherited Destroy;
end;
However, the preceding overloadNewInstanceCompared,VCLThe method defect is that the user cannot be prevented from creating the user's instance multiple times. The following Code respectively
CallTClipboardClass andTSingleConfigClassCreateMethod twice, and then compare the memory address of the Instance obtained after the two calls to determine whether the class is
Created several times:
procedure TForm1.btn1Click(Sender: TObject);
var
P1:Pointer;
P2:Pointer;
begin
P1:=TClipboard.Create();
P2:=Clipboard;
ShowMessage(IntToStr(Integer(p1)));
ShowMessage(IntToStr(Integer(p2)));
end;
procedure TForm1.btn2Click(Sender: TObject);
var
P1:Pointer;
P2:Pointer;
begin
P1:=TSingleConfig.Create();
P2:=TSingleConfig.Create();
ShowMessage(IntToStr(Integer(p1)));
ShowMessage(IntToStr(Integer(p2)));
end;
You can see the running resultTClipboardClass constructor returns different addresses after two calls, whileTSingleConfigThe returned address is the same.
We can see thatNewInstanceThe method is more rigorous than the error.
From: http://delphi.sharpplus.com/Delphi/singleton.htm