Sign in Join
Wiki copytemporary

Singleton Pattern: what changed

Revision 3 to 4. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Introduction
22
3-Considered one of the simplest patterns, it probably is the most discussed pattern: the singleton. What is so difficult to this pattern? Well, no matter the language in which you implement it, you have to do some counter intuitive things to reap all the benefits of the pattern. Every programming language has it's own quirks with this pattern, FreePascal is no exception. As a result, any implementation may lead to discussion and the choices you make for the implementation will be against the principles of another programmer. The implementation of this pattern is never ideal, the approaches provided in this article included. Yet, I hope this article is useful for you.
3+Considered one of the simplest patterns, it probably is the most discussed pattern: the singleton. What is so difficult to this pattern? Well, no matter the language in which you implement it, you have to do some counter intuitive things to reap all the benefits of the pattern. Every programming language has it's own quirks with this pattern, FreePascal is no exception. As a result, any implementation may lead to discussion and the choices you make for the implementation will be against the principles of another programmer. The implementation of this pattern is never ideal, the approaches provided in this article included. Yet, I hope this article is useful for you.
44
55## What You Will Learn
66
7-- The benefits of the Singleton pattern and why to avoid it
8-- Global variables and class variables in FreePascal
9-- How to hide the constructor and keep it private
7+ * The benefits of the Singleton pattern and why to avoid it
8+ * Global variables and class variables in FreePascal
9+ * How to hide the constructor and keep it private
1010
1111## Acknowledgement
1212
13-I didn't think up the examples and the arguments. I found the examples in forum discussions and their archives. This article is a overview of the discussion about singletons and a collection of the usable examples I found.
13+I didn't think up the examples and the arguments. I found the examples in forum discussions and their archives. This article is a overview of the discussion about singletons and a collection of the usable examples I found.
1414
15-- [Making a Singleton class](http://community.freepascal.org:10000/bboards/message?message_id=234708&forum_id=24097)
16-- [Implementing a true Singleton - Can we decrease the visibility of a method?](http://lists.freepascal.org/lists/fpc-pascal/2006-December/012826.html)
17-- [Warning: Constructor should be public](http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg13833.html)
18-- [Compiler Warning: Constructor should be public](http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg18257.html)
19-- TDockManager
20-- Printers4Lazarus package
15+ * [Making a Singleton class](<http://community.freepascal.org:10000/bboards/message?message_id=234708&forum_id=24097>)
16+ * [Implementing a true Singleton - Can we decrease the visibility of a method?](<http://lists.freepascal.org/lists/fpc-pascal/2006-December/012826.html>)
17+ * [Warning: Constructor should be public](<http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg13833.html>)
18+ * [Compiler Warning: Constructor should be public](<http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg18257.html>)
19+ * TDockManager
20+ * Printers4Lazarus package
2121
2222# The Pattern
2323
2424## The diagram
2525
26-![The Singleton pattern](/wiki-images/5/56/250pxSingleton.png)\
27-The Singleton pattern is described in the above image. The Singleton class defines a private class variable that holds the Singleton instance. The class method *GetInstance* creates that instance once and only once and returns it to the client. The constructor method 'Singleton()' is private and thus not visible to the client. The Design Patterns book lists the following benefits:
26+[![The Singleton pattern](/wiki-images/5/56/250pxSingleton.png)](</File:250pxSingleton.png> "The Singleton pattern")
2827
29-- Controlled access to sole instance
30-- Reduced namespace
31-- Permits refinement of operations and representation
32-- Permits variable number of instances (extend the class to allow a controlled number of instances if designer wants to allow such a situation)
33-- More flexible than class operations
28+The Singleton pattern is described in the above image. The Singleton class defines a private class variable that holds the Singleton instance. The class method _GetInstance_ creates that instance once and only once and returns it to the client. The constructor method 'Singleton()' is private and thus not visible to the client. The Design Patterns book lists the following benefits:
3429
35-## The Singleton Client
30+ * Controlled access to sole instance
31+ * Reduced namespace
32+ * Permits refinement of operations and representation
33+ * Permits variable number of instances (extend the class to allow a controlled number of instances if designer wants to allow such a situation)
34+ * More flexible than class operations
3635
37-The following program would be typical use of a singleton.
36+## The Singleton Client
3837
39-``` pascal
38+The following program would be typical use of a singleton.
39+```
4040program TrueSingleton;
41-
42- {$mode objfpc}{$H+}
43-
44- uses
45- {$IFDEF UNIX}{$IFDEF UseCThreads}
46- cthreads,
47- {$ENDIF}{$ENDIF}
48- Classes, Singleton2
49- { you can add units after this };
50-
51- {$R TrueSingleton.res}
52- var
53- s1, s2: TSingleton;
54-
55- begin
56- s1:= TSingleton.GetInstance;
57- s1.name := 'one';
58- writeln('name of s1: '+s1.name);
59-
60- s2:= TSingleton.GetInstance;
61- s2.name := 'two';
62-
63- writeln('name of s1: '+s1.name);
64- writeln('name of s2: '+s2.name);
65- //writeln('name of singleton: ' + Singleton.name);
66- readln;
67- end.
41+
42+ {$mode objfpc}{$H+}
43+
44+ uses
45+ {$IFDEF UNIX}{$IFDEF UseCThreads}
46+ cthreads,
47+ {$ENDIF}{$ENDIF}
48+ Classes, Singleton2
49+ { you can add units after this };
50+
51+ {$R TrueSingleton.res}
52+ var
53+ s1, s2: TSingleton;
54+
55+ begin
56+ s1:= TSingleton.GetInstance;
57+ s1.name := 'one';
58+ writeln('name of s1: '+s1.name);
59+
60+ s2:= TSingleton.GetInstance;
61+ s2.name := 'two';
62+
63+ writeln('name of s1: '+s1.name);
64+ writeln('name of s2: '+s2.name);
65+ //writeln('name of singleton: ' + Singleton.name);
66+ readln;
67+ end.
6868```
6969
70-That is, if the singleton would work according to the pattern. The *GetInstance* method is a class method that returns the only available instance. We will help our user, the programmer, if the constructor *Create* would not show up in the code completion at all. This helps our users to remember that they should use *GetInstance*. A problem here however is that FreePascal, in contrast to other languages, doesn't require a specific name as constructor. *Init* is just as good a name for a constructor as *Create* is.
71-
72-The correct output will look like this:
70+That is, if the singleton would work according to the pattern. The _GetInstance_ method is a class method that returns the only available instance. We will help our user, the programmer, if the constructor _Create_ would not show up in the code completion at all. This helps our users to remember that they should use _GetInstance_. A problem here however is that FreePascal, in contrast to other languages, doesn't require a specific name as constructor. _Init_ is just as good a name for a constructor as _Create_ is.
7371
74-```text
72+The correct output will look like this:
73+```
7574name of s1: one
76- name of s1: two
77- name of s2: two
75+ name of s1: two
76+ name of s2: two
7877```
7978
80-When the correct output is produced, `Singleton.GetInstance` will return the singleton instance and the name of both `s1` and `s2` will always be the same. The wrong output will look like this:
81-
82-```text
79+When the correct output is produced, `Singleton.GetInstance` will return the singleton instance and the name of both `s1` and `s2` will always be the same. The wrong output will look like this:
80+```
8381name of s1: one
84- name of s1: one
85- name of s2: two
82+ name of s1: one
83+ name of s2: two
8684```
8785
88-When the wrong output is produced, a second instance is created that has its own name.
86+When the wrong output is produced, a second instance is created that has its own name.
8987
9088## Nice Pattern, Don't Use It
9189
92-Or at least think it over before you use it. There are many reasons to not use a singleton. Really, there are more reasons not to use a singleton than there are reasons to use a singleton. See the [Drawbacks and Reference sections](https://en.wikipedia.org/w/index.php?title=Singleton_pattern&oldid=397293289#Drawbacks) of an old version of the WikiPedia article discussing singletons. The main reasons:
90+Or at least think it over before you use it. There are many reasons to not use a singleton. Really, there are more reasons not to use a singleton than there are reasons to use a singleton. See the [Drawbacks and Reference sections](<https://en.wikipedia.org/w/index.php?title=Singleton_pattern&oldid=397293289#Drawbacks>) of an old version of the WikiPedia article discussing singletons. The main reasons:
9391
94-- Difficult to test. Because of its nature, singletons are hard to replace for testing.
95-- Singletons make dependencies unclear. Although the singleton comes from another unit, you cannot see in the interface of your object that the singleton is used. Well, the **uses** section gives a clue, but that doesn't say *where* exactly it is used.
92+ * Difficult to test. Because of its nature, singletons are hard to replace for testing.
93+ * Singletons make dependencies unclear. Although the singleton comes from another unit, you cannot see in the interface of your object that the singleton is used. Well, the **uses** section gives a clue, but that doesn't say _where_ exactly it is used.
9694
97-Singletons are commonly used for shared resources or 'engines':
95+Singletons are commonly used for shared resources or 'engines':
9896
99-- Printers
100-- Databases
101-- Loggers
97+ * Printers
98+ * Databases
99+ * Loggers
102100
103-To avoid the use of too many singletons, try to avoid them and use only one in your whole application. For example, you may want to create a toolbox (aka [[http://martinfowler.com/eaaCatalog/registry.html Registry]]) for your application. Now the toolbox knows the printer, database or logger and your code queries the toolbox for instances. Your code depends on the toolbox and the toolbox depends on the resources that can be queried. This reduces the dependencies from a lot of singleton to only one singleton.
101+To avoid the use of too many singletons, try to avoid them and use only one in your whole application. For example, you may want to create a toolbox (aka [[Registry](<http://martinfowler.com/eaaCatalog/registry.html>)]) for your application. Now the toolbox knows the printer, database or logger and your code queries the toolbox for instances. Your code depends on the toolbox and the toolbox depends on the resources that can be queried. This reduces the dependencies from a lot of singleton to only one singleton.
104102
105-Another idea is to use [[http://www.theserverside.com/news/1321158/A-beginners-guide-to-Dependency-Injection Dependency Injection]]. If an object 'B' needs another object 'A' to function properly, then hand the object 'A' to the constructor of the class 'B'. This at least makes clear that the class B depends on A in the interface.
103+Another idea is to use [[Dependency Injection](<http://www.theserverside.com/news/1321158/A-beginners-guide-to-Dependency-Injection>)]. If an object 'B' needs another object 'A' to function properly, then hand the object 'A' to the constructor of the class 'B'. This at least makes clear that the class B depends on A in the interface.
106104
107-To improve testing of your code, you may want to have your singletons implement an interface. The *GetInstance* method or function may then return an instance that conforms to the interface. Depending on whatever (compilation directives etc.) the *GetInstance* method can return the 'real' object or a mock-up.
105+To improve testing of your code, you may want to have your singletons implement an interface. The _GetInstance_ method or function may then return an instance that conforms to the interface. Depending on whatever (compilation directives etc.) the _GetInstance_ method can return the 'real' object or a mock-up.
108106
109-In the rest of this article I discuss how to create a singleton.
107+In the rest of this article I discuss how to create a singleton.
110108
111109# Going Global
112110
113111## In Your (Inter)Face
114112
115-In Free Pascal it is quite common to define a global variable for the Singleton pattern. All through the source code of FreePascal and Lazarus you will find examples of this. The idea is to create an instance at initialization of the unit file and then use it when needed. The client programmer should just know that there is a global instance and that that global instance should be used. Every programmer writes and reads full documentation, so usually this is no problem.
116-
117-``` pascal
113+In Free Pascal it is quite common to define a global variable for the Singleton pattern. All through the source code of FreePascal and Lazarus you will find examples of this. The idea is to create an instance at initialization of the unit file and then use it when needed. The client programmer should just know that there is a global instance and that that global instance should be used. Every programmer writes and reads full documentation, so usually this is no problem.
114+```
118115unit GlobalVariableSingleton;
119-
120- {$mode objfpc}{$H+}
121-
122- interface
123-
124- type
125- TSingleton = class
126- name: String;
127- constructor create;
128- end;
129-
130- var
131- Singleton: TSingleton = nil;
132-
133- implementation
134- {* Something happens out here *}
135-
136- initialization
137- Singleton := TSingleton.Create;
138-
139- end.
116+
117+ {$mode objfpc}{$H+}
118+
119+ interface
120+
121+ type
122+ TSingleton = class
123+ name: String;
124+ constructor create;
125+ end;
126+
127+ var
128+ Singleton: TSingleton = nil;
129+
130+ implementation
131+ {* Something happens out here *}
132+
133+ initialization
134+ Singleton := TSingleton.Create;
135+
136+ end.
140137```
141138
142-When this unit is loaded, the singleton is instantiated and can be used. The initialization takes place when the program is started, so the singleton is always present. This violates the reduction of namespace, the namespace is polluted by a global variable that is waiting for use. Even if the programmer is not interested in the instance, but is only interested in other functionality in your unit, the instance is created and will use memory. On the other hand, we wanted to have a singleton so that we would use it right? There is no probability involved, we will use the instance. So, why not create the instance when we startup the application? With the above definition of a global variable the instantiation is not controlled. Any programmer can still instantiate the TSingleton. This can be improved with documentation and a constructor that warns against instantiation after the global variable is created. Something like the following:
143-
144-``` pascal
139+When this unit is loaded, the singleton is instantiated and can be used. The initialization takes place when the program is started, so the singleton is always present. This violates the reduction of namespace, the namespace is polluted by a global variable that is waiting for use. Even if the programmer is not interested in the instance, but is only interested in other functionality in your unit, the instance is created and will use memory. On the other hand, we wanted to have a singleton so that we would use it right? There is no probability involved, we will use the instance. So, why not create the instance when we startup the application? With the above definition of a global variable the instantiation is not controlled. Any programmer can still instantiate the TSingleton. This can be improved with documentation and a constructor that warns against instantiation after the global variable is created. Something like the following:
140+```
145141constructor TSingleton.Create;
146- begin
147- If Assigned(Singleton) then
148- Raise Exception.Create('Please use the global variable Singleton');
149- inherited Create;
150- end;
142+ begin
143+ If Assigned(Singleton) then
144+ Raise Exception.Create('Please use the global variable Singleton');
145+ inherited Create;
146+ end;
151147```
152148
153-However, such a constructor only warns at run time and doesn't help at design time. An alternative to the if statement could be an assert. With an assert the detection would be moved to test time, which – as you know - we all do and happens far before run time. However, an assert doesn't even help at run time since the asserts are not linked in for the run time application. I agree, it does seem to happen that not all code is always tested. In the given constructor the program at least breaks due to an unhandled exception. The programmer of your client will probably work around that annoyance with a `try ... except` statement. Even though programmers can work around the issue, their code doesn't work so why should they? The global variable is not a singleton at design time, the constructor will still show up. However, it will certainly be a singleton at run time. The typical client code is:
154-
155-``` pascal
149+However, such a constructor only warns at run time and doesn't help at design time. An alternative to the if statement could be an assert. With an assert the detection would be moved to test time, which – as you know - we all do and happens far before run time. However, an assert doesn't even help at run time since the asserts are not linked in for the run time application. I agree, it does seem to happen that not all code is always tested. In the given constructor the program at least breaks due to an unhandled exception. The programmer of your client will probably work around that annoyance with a `try ... except` statement. Even though programmers can work around the issue, their code doesn't work so why should they? The global variable is not a singleton at design time, the constructor will still show up. However, it will certainly be a singleton at run time. The typical client code is:
150+```
156151program TrueSingleton;
157-
158- {$mode objfpc}{$H+}
159-
160- uses
161- {$IFDEF UNIX}{$IFDEF UseCThreads}
162- cthreads,
163- {$ENDIF}{$ENDIF}
164- Classes, GlobalVariableSingleton
165- { you can add units after this };
166-
167- {$R TrueSingleton.res}
168- var
169- s1, s2: TSingleton;
170-
171- begin
172- s1:= Singleton;
173- s1.name := 'one';
174- writeln('name of s1: '+s1.name);
175-
176- s2:= Singleton;
177- s2.name := 'two';
178-
179- writeln('name of s1: '+s1.name);
180- writeln('name of s2: '+s2.name);
181- //writeln('name of singleton: ' + Singleton.name);
182- readln;
183- end.
152+
153+ {$mode objfpc}{$H+}
154+
155+ uses
156+ {$IFDEF UNIX}{$IFDEF UseCThreads}
157+ cthreads,
158+ {$ENDIF}{$ENDIF}
159+ Classes, GlobalVariableSingleton
160+ { you can add units after this };
161+
162+ {$R TrueSingleton.res}
163+ var
164+ s1, s2: TSingleton;
165+
166+ begin
167+ s1:= Singleton;
168+ s1.name := 'one';
169+ writeln('name of s1: '+s1.name);
170+
171+ s2:= Singleton;
172+ s2.name := 'two';
173+
174+ writeln('name of s1: '+s1.name);
175+ writeln('name of s2: '+s2.name);
176+ //writeln('name of singleton: ' + Singleton.name);
177+ readln;
178+ end.
184179```
185180
186-Of course, instead of assigning the global variable to a local variable you can also use the global variable directly.
181+Of course, instead of assigning the global variable to a local variable you can also use the global variable directly.
187182
188183## Up Your Implementation
189184
190-Notice how in the *GlobalVariableSingleton* unit the global variable is defined in the interface section. This is what makes the variable *Singleton* a global variable. If you put the variable in the implementation section, the variable will only be available for code in the implementation section. As such, a variable defined in the implementation section acts similar to a class or package variable. The implementation variable can be used by all the code in the unit but not outside that unit. The interface variable is public, can be used inside and outside the unit. This is used in the following code.
191-
192-``` pascal
185+Notice how in the _GlobalVariableSingleton_ unit the global variable is defined in the interface section. This is what makes the variable _Singleton_ a global variable. If you put the variable in the implementation section, the variable will only be available for code in the implementation section. As such, a variable defined in the implementation section acts similar to a class or package variable. The implementation variable can be used by all the code in the unit but not outside that unit. The interface variable is public, can be used inside and outside the unit. This is used in the following code.
186+```
193187unit GlobalFunctionSingleton;
194-
195- {$mode objfpc}{$H+}
196-
197- interface
198-
199- uses
200- Classes, SysUtils;
201- type
202- TSingleton = class
203- public
204- name : String;
205- constructor Create;
206- end;
207-
208- function GetSingleton : TSingleton;
209-
210- implementation
211- var
212- Singleton : TSingleton = nil;
213-
214- constructor TSingleton.Create;
215- begin
216- assert(Singleton=nil, 'illegal recreation of Singleton.');
217- inherited Create;
218- Singleton := self;
219- end;
220-
221- function GetSingleton : TSingleton;
222- Begin
223- If(Singleton = nil) then
224- raise Exception.Create('Singleton not created during initialization.');
225- Result := Singleton;
226- end;
227-
228- initialization
229- Singleton := TSingleton.Create;
230- end.
188+
189+ {$mode objfpc}{$H+}
190+
191+ interface
192+
193+ uses
194+ Classes, SysUtils;
195+ type
196+ TSingleton = class
197+ public
198+ name : String;
199+ constructor Create;
200+ end;
201+
202+ function GetSingleton : TSingleton;
203+
204+ implementation
205+ var
206+ Singleton : TSingleton = nil;
207+
208+ constructor TSingleton.Create;
209+ begin
210+ assert(Singleton=nil, 'illegal recreation of Singleton.');
211+ inherited Create;
212+ Singleton := self;
213+ end;
214+
215+ function GetSingleton : TSingleton;
216+ Begin
217+ If(Singleton = nil) then
218+ raise Exception.Create('Singleton not created during initialization.');
219+ Result := Singleton;
220+ end;
221+
222+ initialization
223+ Singleton := TSingleton.Create;
224+ end.
231225```
232226
233-In this case, the singleton instance is not a global variable (it is defined in the implementation section) and cannot be used outside the implementation section. The *GetSingleton* function however can be used outside the unit. But in contrast to the pattern diagram, it is not a class method but a good old global function. The advantage over the previous implementation is that the *GetSingleton* function can contain more functionality than just returning the one instance. For example, the function could be used to hand out instances from a pool of singletons. The client code is as follows:
234-
235-``` pascal
227+In this case, the singleton instance is not a global variable (it is defined in the implementation section) and cannot be used outside the implementation section. The _GetSingleton_ function however can be used outside the unit. But in contrast to the pattern diagram, it is not a class method but a good old global function. The advantage over the previous implementation is that the _GetSingleton_ function can contain more functionality than just returning the one instance. For example, the function could be used to hand out instances from a pool of singletons. The client code is as follows:
228+```
236229program TrueSingleton;
237-
238- {$mode objfpc}{$H+}
239-
240- uses
241- {$IFDEF UNIX}{$IFDEF UseCThreads}
242- cthreads,
243- {$ENDIF}{$ENDIF}
244- Classes, GlobalFunctionSingleton
245- { you can add units after this };
246-
247- {$R TrueSingleton.res}
248- var
249- s1, s2: TSingleton;
250-
251- begin
252- s1:= GetSingleton;
253- s1.name := 'one';
254- writeln('name of s1: '+s1.name);
255-
256- s2:= GetSingleton;
257- s2.name := 'two';
258-
259- writeln('name of s1: '+s1.name);
260- writeln('name of s2: '+s2.name);
261- //writeln('name of singleton: ' + Singleton.name);
262- readln;
263- end.
230+
231+ {$mode objfpc}{$H+}
232+
233+ uses
234+ {$IFDEF UNIX}{$IFDEF UseCThreads}
235+ cthreads,
236+ {$ENDIF}{$ENDIF}
237+ Classes, GlobalFunctionSingleton
238+ { you can add units after this };
239+
240+ {$R TrueSingleton.res}
241+ var
242+ s1, s2: TSingleton;
243+
244+ begin
245+ s1:= GetSingleton;
246+ s1.name := 'one';
247+ writeln('name of s1: '+s1.name);
248+
249+ s2:= GetSingleton;
250+ s2.name := 'two';
251+
252+ writeln('name of s1: '+s1.name);
253+ writeln('name of s2: '+s2.name);
254+ //writeln('name of singleton: ' + Singleton.name);
255+ readln;
256+ end.
264257```
265258
266-It works, but I have not seen this applied in any source code.
259+It works, but I have not seen this applied in any source code.
267260
268261# Classy Implementation
269262
270263## Simple Singleton
271264
272-The following code presents a very simple singleton.
273-
274-``` pascal
265+The following code presents a very simple singleton.
266+```
275267unit Singleton1;
276-
277- {$mode objfpc}{$H+}
278-
279- interface
280-
281- type
282- TSingleton = class
283- name: String;
284- constructor create;
285- end;
286-
287- implementation
288-
289- var
290- Singleton: TSingleton = nil;
291-
292- constructor TSingleton.Create;
293- begin
294- if not(assigned(Singleton)) then begin
295- inherited;
296- (*... do initializations ...*)
297- Singleton := self;
298- end else begin
299- self := Singleton;
300- end;
301- end;
302-
303- end.
268+
269+ {$mode objfpc}{$H+}
270+
271+ interface
272+
273+ type
274+ TSingleton = class
275+ name: String;
276+ constructor create;
277+ end;
278+
279+ implementation
280+
281+ var
282+ Singleton: TSingleton = nil;
283+
284+ constructor TSingleton.Create;
285+ begin
286+ if not(assigned(Singleton)) then begin
287+ inherited;
288+ (*... do initializations ...*)
289+ Singleton := self;
290+ end else begin
291+ self := Singleton;
292+ end;
293+ end;
294+
295+ end.
304296```
305297
306-In the *Singleton1* unit, notice the following:
298+In the _Singleton1_ unit, notice the following:
307299
308-- The Singleton variable is defined in the **implementation** section. This makes the variable invisible outside the unit.
309-- A public constructor is used.
300+ * The Singleton variable is defined in the **implementation** section. This makes the variable invisible outside the unit.
301+ * A public constructor is used.
310302
311-Free Pascal doesn't allow for class variables and class properties. Only procedures and functions can be modified with the class keyword. Defining the 'static' variable in the implementation section is the closest we can get to a static variable. At initialization this variable is set to **nil**, so no memory is used yet. Although this implementation works, the `self := Singleton;` bugs me. I didn't try it, but I assume this allows for memory leaks. Even if it doesn't allow for memory leaks, it just doesn't look right.
303+Free Pascal doesn't allow for class variables and class properties. Only procedures and functions can be modified with the class keyword. Defining the 'static' variable in the implementation section is the closest we can get to a static variable. At initialization this variable is set to **nil** , so no memory is used yet. Although this implementation works, the `self := Singleton;` bugs me. I didn't try it, but I assume this allows for memory leaks. Even if it doesn't allow for memory leaks, it just doesn't look right.
312304
313305## Why It Is Different In Pascal
314306
315-Then why not implement the singleton just like it is shown in the Pattern diagram? Well, here we go:
316-
317-``` pascal
307+Then why not implement the singleton just like it is shown in the Pattern diagram? Well, here we go:
308+```
318309unit Singleton2;
319-
320- {$mode objfpc}{$H+}
321-
322- interface
323-
324- uses
325- Classes, SysUtils;
326-
327- type
328- TSingleton = class
329- private
330- constructor Create;
331- public
332- name: String;
333- class function GetInstance : TSingleton;
334- end;
335-
336- implementation
337- var
338- Singleton : TSingleton = nil;
339-
340- constructor TSingleton.Create;
341- begin
342- inherited Create;
343- end;
344-
345- class function TSingleton.GetInstance : TSingleton;
346- begin
347- if Singleton = nil then
348- Singleton := TSingleton.Create;
349- Result := Singleton;
350- end;
351-
352- end.
310+
311+ {$mode objfpc}{$H+}
312+
313+ interface
314+
315+ uses
316+ Classes, SysUtils;
317+
318+ type
319+ TSingleton = class
320+ private
321+ constructor Create;
322+ public
323+ name: String;
324+ class function GetInstance : TSingleton;
325+ end;
326+
327+ implementation
328+ var
329+ Singleton : TSingleton = nil;
330+
331+ constructor TSingleton.Create;
332+ begin
333+ inherited Create;
334+ end;
335+
336+ class function TSingleton.GetInstance : TSingleton;
337+ begin
338+ if Singleton = nil then
339+ Singleton := TSingleton.Create;
340+ Result := Singleton;
341+ end;
342+
343+ end.
353344```
354345
355-The problem with the *Singleton2* unit is that the program will work with the following client code:
356-
357-``` pascal
346+The problem with the _Singleton2_ unit is that the program will work with the following client code:
347+```
358348program TrueSingleton;
359-
360- {$mode objfpc}{$H+}
361-
362- uses
363- {$IFDEF UNIX}{$IFDEF UseCThreads}
364- cthreads,
365- {$ENDIF}{$ENDIF}
366- Classes, Singleton2
367- { you can add units after this };
368-
369- {$R TrueSingleton.res}
370- var
371- s1, s2: TSingleton;
372-
373- begin
374- s1:= TSingleton.Create;
375- s1.name := 'one';
376- writeln('name of s1: '+s1.name);
377-
378- s2:= TSingleton.Create;
379- s2.name := 'two';
380-
381- writeln('name of s1: '+s1.name);
382- writeln('name of s2: '+s2.name);
383- //writeln('name of singleton: ' + Singleton.name);
384- readln;
385- end.
349+
350+ {$mode objfpc}{$H+}
351+
352+ uses
353+ {$IFDEF UNIX}{$IFDEF UseCThreads}
354+ cthreads,
355+ {$ENDIF}{$ENDIF}
356+ Classes, Singleton2
357+ { you can add units after this };
358+
359+ {$R TrueSingleton.res}
360+ var
361+ s1, s2: TSingleton;
362+
363+ begin
364+ s1:= TSingleton.Create;
365+ s1.name := 'one';
366+ writeln('name of s1: '+s1.name);
367+
368+ s2:= TSingleton.Create;
369+ s2.name := 'two';
370+
371+ writeln('name of s1: '+s1.name);
372+ writeln('name of s2: '+s2.name);
373+ //writeln('name of singleton: ' + Singleton.name);
374+ readln;
375+ end.
386376```
387377
388-It is difficult to see the problem. In the *Singleton2* unit we made the constructor private. Run the client code, and the compiler complains about the constructor not being public, but after that the program works and shows that the code doesn't work as a singleton. Two different instances will be created. We learn from this that although we reduced the visibility of the constructor, the *TObject.Create* constructor is still visible.
378+It is difficult to see the problem. In the _Singleton2_ unit we made the constructor private. Run the client code, and the compiler complains about the constructor not being public, but after that the program works and shows that the code doesn't work as a singleton. Two different instances will be created. We learn from this that although we reduced the visibility of the constructor, the _TObject.Create_ constructor is still visible.
389379
390380## The 'constructor should be public' Singleton
391381
392-A *small* change makes a big difference:
393-
394-``` pascal
382+A _small_ change makes a big difference:
383+```
395384unit Singleton3;
396-
397- {$mode objfpc}{$H+}
398-
399- interface
400-
401- uses
402- Classes, SysUtils;
403-
404- type
405- TSingleton = class
406- private
407- constructor Init;
408- public
409- name: String;
410- class function Create: TSingleton;
411- end;
412-
413- implementation
414- var
415- Singleton : TSingleton = nil;
416-
417- constructor TSingleton.Init;
418- begin
419- inherited Create;
420- end;
421-
422- class function TSingleton.Create: TSingleton;
423- begin
424- if Singleton = nil then
425- Singleton := TSingleton.Init;
426- Result := Singleton;
427- end;
428-
429- end.
385+
386+ {$mode objfpc}{$H+}
387+
388+ interface
389+
390+ uses
391+ Classes, SysUtils;
392+
393+ type
394+ TSingleton = class
395+ private
396+ constructor Init;
397+ public
398+ name: String;
399+ class function Create: TSingleton;
400+ end;
401+
402+ implementation
403+ var
404+ Singleton : TSingleton = nil;
405+
406+ constructor TSingleton.Init;
407+ begin
408+ inherited Create;
409+ end;
410+
411+ class function TSingleton.Create: TSingleton;
412+ begin
413+ if Singleton = nil then
414+ Singleton := TSingleton.Init;
415+ Result := Singleton;
416+ end;
417+
418+ end.
430419```
431420
432-The *Init* constructor provides us with the constructor we need to avoid illegally hiding the TObject constructor. The *Init* constructor is also private. The *Create* **function** hides the *TObject.Create* constructor. This code works. Using the above we have controlled access to the singleton. We also do not pollute the namespace with global variables. We can create additional methods as much as we want. Also, if we declare an array of singletons in the implementation section we can provide additional, but limited instances of the singleton. And, we do not need additional static methods other than the *Create* function. All benefits of the singleton pattern are thus achieved. Typical client code now needs to look like the following:
433-
434-``` pascal
421+The _Init_ constructor provides us with the constructor we need to avoid illegally hiding the TObject constructor. The _Init_ constructor is also private. The _Create_ **function** hides the _TObject.Create_ constructor. This code works. Using the above we have controlled access to the singleton. We also do not pollute the namespace with global variables. We can create additional methods as much as we want. Also, if we declare an array of singletons in the implementation section we can provide additional, but limited instances of the singleton. And, we do not need additional static methods other than the _Create_ function. All benefits of the singleton pattern are thus achieved. Typical client code now needs to look like the following:
422+```
435423program TrueSingleton;
436-
437- {$mode objfpc}{$H+}
438-
439- uses
440- {$IFDEF UNIX}{$IFDEF UseCThreads}
441- cthreads,
442- {$ENDIF}{$ENDIF}
443- Classes, Singleton3
444- { you can add units after this };
445-
446- {$R TrueSingleton.res}
447- var
448- s1, s2: TSingleton;
449-
450- begin
451- s1:= TSingleton.Create;
452- s1.name := 'one';
453- writeln('name of s1: '+s1.name);
454-
455- s2:= TSingleton.Create;
456- s2.name := 'two';
457-
458- writeln('name of s1: '+s1.name);
459- writeln('name of s2: '+s2.name);
460- //writeln('name of singleton: ' + Singleton.name);
461- readln;
462- end.
424+
425+ {$mode objfpc}{$H+}
426+
427+ uses
428+ {$IFDEF UNIX}{$IFDEF UseCThreads}
429+ cthreads,
430+ {$ENDIF}{$ENDIF}
431+ Classes, Singleton3
432+ { you can add units after this };
433+
434+ {$R TrueSingleton.res}
435+ var
436+ s1, s2: TSingleton;
437+
438+ begin
439+ s1:= TSingleton.Create;
440+ s1.name := 'one';
441+ writeln('name of s1: '+s1.name);
442+
443+ s2:= TSingleton.Create;
444+ s2.name := 'two';
445+
446+ writeln('name of s1: '+s1.name);
447+ writeln('name of s2: '+s2.name);
448+ //writeln('name of singleton: ' + Singleton.name);
449+ readln;
450+ end.
463451```
464452
465-Notice how this program uses the *Create* method, not the *GetInstance* method. But, look at the class definition again. *Create* is not a constructor it is a class method that returns the singleton instance. *Init* is the constructor.
453+Notice how this program uses the _Create_ method, not the _GetInstance_ method. But, look at the class definition again. _Create_ is not a constructor it is a class method that returns the singleton instance. _Init_ is the constructor.
466454
467455## Hide That For Me
468456
469-When compiling, the compiler warns that the constructor is not public. So, now you are warned. You can choose to ignore the warning, because the code is really what you want. You can also suppress the warning. The message code for the 'Constructor should be public' warning is 3018. To suppress the warning add `-vm3018` to the command line of the compiler. In Lazarus you can deselect the message {From the **Project** menu, choose **Project Options**. Then, in the **Options for Project:** dialog, open the **Compiler Options** branch in the navigation pane and click **Messages**. Now deselect '(W)Constructor should be public' in the compiler messages list.}
457+When compiling, the compiler warns that the constructor is not public. So, now you are warned. You can choose to ignore the warning, because the code is really what you want. You can also suppress the warning. The message code for the 'Constructor should be public' warning is 3018. To suppress the warning add `-vm3018` to the command line of the compiler. In Lazarus you can deselect the message {From the **Project** menu, choose **Project Options**. Then, in the **Options for Project:** dialog, open the **Compiler Options** branch in the navigation pane and click **Messages**. Now deselect '(W)Constructor should be public' in the compiler messages list.}
470458
471459# Discussion Of The Options
472460
473-In this part we will pay attention to some of the discussions.
461+In this part we will pay attention to some of the discussions.
474462
475463## Reducing the visibility of the constructor
476464
477-Of course there is a reason why a constructor should be public. The Free Pascal compiler thus gives a warning when the constructor is made private. However, why does FreePascal give the warning? Other programming languages allow private constructors without a problem. Apart from that it is bad Pascal programming behavior, I don't know the answer. Maybe, since it is a warning, the reasoning may be that if the constructor is not public, then there is no way to create the object and what is the use of a class if you cannot make an object out of it? To sum things up, the argument is as follows:
478-
479-``` pascal
465+Of course there is a reason why a constructor should be public. The Free Pascal compiler thus gives a warning when the constructor is made private. However, why does FreePascal give the warning? Other programming languages allow private constructors without a problem. Apart from that it is bad Pascal programming behavior, I don't know the answer. Maybe, since it is a warning, the reasoning may be that if the constructor is not public, then there is no way to create the object and what is the use of a class if you cannot make an object out of it? To sum things up, the argument is as follows:
466+```
480467The reason you can't lower the visibility of the constructor or any
481-method for that matter... A class interface (implementation section) ,
482-even for TObject as in your example, is a contract of how you can use
483-that class and what is available to you. By lowering the visibility
484-of a method or constructor in a descendant class, you are breaking the
485-contract previously defined. This is a BIG no-no, hence the reason it
486-is not allowed.
468+ method for that matter... A class interface (implementation section) ,
469+ even for TObject as in your example, is a contract of how you can use
470+ that class and what is available to you. By lowering the visibility
471+ of a method or constructor in a descendant class, you are breaking the
472+ contract previously defined. This is a BIG no-no, hence the reason it
473+ is not allowed.
487474```
488475
489476## Design Time Help vs. Run Time Breaking
490477
491-The following arguments may lead you to choose the Singleton3 unit as example implementation:
478+The following arguments may lead you to choose the Singleton3 unit as example implementation:
492479
493-- The Singleton3 provides design time guidance. Possible alternatives that are more in the spirit of Pascal give run time break downs, or at best testing time messages. Design time guidance is preferred in my opinion.
494-- If you want to avoid multiple instantiation of the class, then why not provide design time help to the client programmer.
495-- In other programming languages it is not bad programming behavior, so FreePascal must have a very good reason to avoid it.
496-- Reducing the visibility of any method of a class should not be allowed except for the constructor.
480+ * The Singleton3 provides design time guidance. Possible alternatives that are more in the spirit of Pascal give run time break downs, or at best testing time messages. Design time guidance is preferred in my opinion.
481+ * If you want to avoid multiple instantiation of the class, then why not provide design time help to the client programmer.
482+ * In other programming languages it is not bad programming behavior, so FreePascal must have a very good reason to avoid it.
483+ * Reducing the visibility of any method of a class should not be allowed except for the constructor.
497484
498485## The pattern is not followed
499486
500-Yes, the pattern is not closely followed. The constructor is called *Init* while in FreePascal there is the convention to call the constructor *Create*. Then on top of that name *Create* is used for the static function instead of the name *GetInstance*. The following arguments are in favor of the most likable implementation:
487+Yes, the pattern is not closely followed. The constructor is called _Init_ while in FreePascal there is the convention to call the constructor _Create_. Then on top of that name _Create_ is used for the static function instead of the name _GetInstance_. The following arguments are in favor of the most likable implementation:
501488
502-- The intent of the pattern is followed and the benefits achieved.
503-- The code is quite nice and well behaved. There are no run-time breaks built in and there are no doubtful constructs in the code.
504-- Some compromises had to be made to make the singleton work in FreePascal.
489+ * The intent of the pattern is followed and the benefits achieved.
490+ * The code is quite nice and well behaved. There are no run-time breaks built in and there are no doubtful constructs in the code.
491+ * Some compromises had to be made to make the singleton work in FreePascal.
505492
506493## The implementations have a problem with multi-threading and synchronization
507494
508-I never saw a good discussion about this, but in discussions about singletons in various programming languages programmers go far to make their singleton multi-threaded and synchronized and a number of other things. The singleton implementations given in this article are not optimized for that.
495+I never saw a good discussion about this, but in discussions about singletons in various programming languages programmers go far to make their singleton multi-threaded and synchronized and a number of other things. The singleton implementations given in this article are not optimized for that.
509496
510497## The singleton class implementation has a problem with platform independence
511498
512-A singleton can never have descendants. What should happen when a descendant class calls **inherited Create**? Also it would be quite wrong to make the singleton descend from anything else but TObject. Now consider platform independence. Look at FreePascal sources where a global variable is used for a printer or whatever central resource. These global variables are by no exception made in the platform specific units, the shared functionality is written in a platform independent unit. Consider how this should be done with a singleton class. (I'll wait here until you find out that a hierarchy of singletons will inevitably cause a mess and will not allow for platform independent code.) Now that you are convinced we can easily say that the singleton class cannot be used with shared functionality, repeating singleton functionality for all platform implementations will cause a maintenance mess.
499+A singleton can never have descendants. What should happen when a descendant class calls **inherited Create**? Also it would be quite wrong to make the singleton descend from anything else but TObject. Now consider platform independence. Look at FreePascal sources where a global variable is used for a printer or whatever central resource. These global variables are by no exception made in the platform specific units, the shared functionality is written in a platform independent unit. Consider how this should be done with a singleton class. (I'll wait here until you find out that a hierarchy of singletons will inevitably cause a mess and will not allow for platform independent code.) Now that you are convinced we can easily say that the singleton class cannot be used with shared functionality, repeating singleton functionality for all platform implementations will cause a maintenance mess.
513500
514501# Conclusion
515502
516-Yes, singletons are possible! Even in FreePascal. But, singletons are not a very good idea in platform independent FreePascal code. Whether you use a class or a global variable, there is no *perfect* implementation of a singleton.
503+Yes, singletons are possible! Even in FreePascal. But, singletons are not a very good idea in platform independent FreePascal code. Whether you use a class or a global variable, there is no _perfect_ implementation of a singleton.
517504
518505---
519-*From the Free Pascal wiki, page "Singleton Pattern", as it stood on 2020-05-08 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
520-Category: Design Patterns
521-Category: FPC
522-Category: Pascal
523-Category: Tutorials
506+*From the Free Pascal wiki, page "Singleton Pattern", as the Internet Archive kept it on 2025-01-22, last changed on 2024-07-31. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history