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 methodsGetInstance
Through static variables
GlobalConfig
Determine the corresponding object first
GlobalConfig
Whether the variable is
nil
, If
nil
Indicates 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 it
GlobalConfig
Variable.
nil
, Returns the created
GlobalConfig
Object. Pass
GlobalConfig
To ensure that the object instance is always only
One (note:
GlobalConfig
Object must be declared in
Implementation
Part, instead of declaring in the unit
Interface
In 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.
Delphi
When an object is released, the variable corresponding to its instance is not automatically set
nil
If you call
GetInstance
Although the global object has been destroyed
Assigned(GlobalConfig)
Still returns true,
So
GetInstance
Returns an incorrect pointer, resulting in
AV
Error. To avoid this situation, you can reload
FreeInstance
Method.
It will always be called during release
FreeInstance
After the object is released
GlobalConfig
Reset
nil
You can.
VCL
Singleton in
In
VCL
There are also many Singleton instances, such as the clipboard class.
TClipboard
Class, in
Clipbrd.pas
The Unit provides instance control technology similar to the above, but it is
Function
Clipboard
To 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 variables
nil
destructor TClipboard.Destroy;
begin
if (FClipboard = Self) then
FClipboard := nil;
inherited Destroy;
end;
However, the preceding overload
NewInstance
Compared,
VCL
The method defect is that the user cannot be prevented from creating the user's instance multiple times. The following Code respectively
Call
TClipboard
Class and
TSingleConfig
Class
Create
Method 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 result
TClipboard
Class constructor returns different addresses after two calls, while
TSingleConfig
The returned address is the same.
We can see that
NewInstance
The method is more rigorous than the error.
From: http://delphi.sharpplus.com/Delphi/singleton.htm