Sign in Join
Wiki copytemporary

Singleton Pattern: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Introduction
22
33Considered 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
77- The benefits of the Singleton pattern and why to avoid it
88- Global variables and class variables in FreePascal
99- How to hide the constructor and keep it private
1010
1111## Acknowledgement
1212
1313I 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
1515- [Making a Singleton class](http://community.freepascal.org:10000/bboards/message?message_id=234708&forum_id=24097)
1616- [Implementing a true Singleton - Can we decrease the visibility of a method?](http://lists.freepascal.org/lists/fpc-pascal/2006-December/012826.html)
1717- [Warning: Constructor should be public](http://www.mail-archive.com/fpc-devel@lists.freepascal.org/msg13833.html)
1818- [Compiler Warning: Constructor should be public](http://www.mail-archive.com/fpc-pascal@lists.freepascal.org/msg18257.html)
1919- TDockManager
2020- Printers4Lazarus package
2121
2222# The Pattern
2323
2424## The diagram
2525
2626![The Singleton pattern](/wiki-images/5/56/250pxSingleton.png)\
2727The 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:
2828
2929- Controlled access to sole instance
3030- Reduced namespace
3131- Permits refinement of operations and representation
3232- Permits variable number of instances (extend the class to allow a controlled number of instances if designer wants to allow such a situation)
3333- More flexible than class operations
3434
3535## The Singleton Client
3636
3737The following program would be typical use of a singleton.
3838
3939``` pascal
4040program TrueSingleton;
4141
4242 {$mode objfpc}{$H+}
4343
4444 uses
4545 {$IFDEF UNIX}{$IFDEF UseCThreads}
4646 cthreads,
4747 {$ENDIF}{$ENDIF}
4848 Classes, Singleton2
4949 { you can add units after this };
5050
5151 {$R TrueSingleton.res}
5252 var
5353 s1, s2: TSingleton;
5454
5555 begin
5656 s1:= TSingleton.GetInstance;
5757 s1.name := 'one';
5858 writeln('name of s1: '+s1.name);
5959
6060 s2:= TSingleton.GetInstance;
6161 s2.name := 'two';
6262
6363 writeln('name of s1: '+s1.name);
6464 writeln('name of s2: '+s2.name);
6565 //writeln('name of singleton: ' + Singleton.name);
6666 readln;
6767 end.
6868```
6969
7070That 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.
7171
7272The correct output will look like this:
7373
74-<code>`name of s1: one`\
74+`name of s1: one`\
7575`name of s1: two`\
76-`name of s2: two`</code>
76+`name of s2: two`
7777
7878When 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:
7979
80-<code>`name of s1: one`\
8180`name of s1: one`\
82-`name of s2: two`</code>
81+`name of s1: one`\
82+`name of s2: two`
8383
8484When the wrong output is produced, a second instance is created that has its own name.
8585
8686## Nice Pattern, Don't Use It
8787
8888Or 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:
8989
9090- Difficult to test. Because of its nature, singletons are hard to replace for testing.
9191- 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.
9292
9393Singletons are commonly used for shared resources or 'engines':
9494
9595- Printers
9696- Databases
9797- Loggers
9898
9999To 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.
100100
101101Another 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.
102102
103103To 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.
104104
105105In the rest of this article I discuss how to create a singleton.
106106
107107# Going Global
108108
109109## In Your (Inter)Face
110110
111111In 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.
112112
113113``` pascal
114114unit GlobalVariableSingleton;
115115
116116 {$mode objfpc}{$H+}
117117
118118 interface
119119
120120 type
121121 TSingleton = class
122122 name: String;
123123 constructor create;
124124 end;
125125
126126 var
127127 Singleton: TSingleton = nil;
128128
129129 implementation
130130 {* Something happens out here *}
131131
132132 initialization
133133 Singleton := TSingleton.Create;
134134
135135 end.
136136```
137137
138138When 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:
139139
140140``` pascal
141141constructor TSingleton.Create;
142142 begin
143143 If Assigned(Singleton) then
144144 Raise Exception.Create('Please use the global variable Singleton');
145145 inherited Create;
146146 end;
147147```
148148
149149However, 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:
150150
151151``` pascal
152152program TrueSingleton;
153153
154154 {$mode objfpc}{$H+}
155155
156156 uses
157157 {$IFDEF UNIX}{$IFDEF UseCThreads}
158158 cthreads,
159159 {$ENDIF}{$ENDIF}
160160 Classes, GlobalVariableSingleton
161161 { you can add units after this };
162162
163163 {$R TrueSingleton.res}
164164 var
165165 s1, s2: TSingleton;
166166
167167 begin
168168 s1:= Singleton;
169169 s1.name := 'one';
170170 writeln('name of s1: '+s1.name);
171171
172172 s2:= Singleton;
173173 s2.name := 'two';
174174
175175 writeln('name of s1: '+s1.name);
176176 writeln('name of s2: '+s2.name);
177177 //writeln('name of singleton: ' + Singleton.name);
178178 readln;
179179 end.
180180```
181181
182182Of course, instead of assigning the global variable to a local variable you can also use the global variable directly.
183183
184184## Up Your Implementation
185185
186186Notice 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.
187187
188188``` pascal
189189unit GlobalFunctionSingleton;
190190
191191 {$mode objfpc}{$H+}
192192
193193 interface
194194
195195 uses
196196 Classes, SysUtils;
197197 type
198198 TSingleton = class
199199 public
200200 name : String;
201201 constructor Create;
202202 end;
203203
204204 function GetSingleton : TSingleton;
205205
206206 implementation
207207 var
208208 Singleton : TSingleton = nil;
209209
210210 constructor TSingleton.Create;
211211 begin
212212 assert(Singleton=nil, 'illegal recreation of Singleton.');
213213 inherited Create;
214214 Singleton := self;
215215 end;
216216
217217 function GetSingleton : TSingleton;
218218 Begin
219219 If(Singleton = nil) then
220220 raise Exception.Create('Singleton not created during initialization.');
221221 Result := Singleton;
222222 end;
223223
224224 initialization
225225 Singleton := TSingleton.Create;
226226 end.
227227```
228228
229229In 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:
230230
231231``` pascal
232232program TrueSingleton;
233233
234234 {$mode objfpc}{$H+}
235235
236236 uses
237237 {$IFDEF UNIX}{$IFDEF UseCThreads}
238238 cthreads,
239239 {$ENDIF}{$ENDIF}
240240 Classes, GlobalFunctionSingleton
241241 { you can add units after this };
242242
243243 {$R TrueSingleton.res}
244244 var
245245 s1, s2: TSingleton;
246246
247247 begin
248248 s1:= GetSingleton;
249249 s1.name := 'one';
250250 writeln('name of s1: '+s1.name);
251251
252252 s2:= GetSingleton;
253253 s2.name := 'two';
254254
255255 writeln('name of s1: '+s1.name);
256256 writeln('name of s2: '+s2.name);
257257 //writeln('name of singleton: ' + Singleton.name);
258258 readln;
259259 end.
260260```
261261
262262It works, but I have not seen this applied in any source code.
263263
264264# Classy Implementation
265265
266266## Simple Singleton
267267
268268The following code presents a very simple singleton.
269269
270270``` pascal
271271unit Singleton1;
272272
273273 {$mode objfpc}{$H+}
274274
275275 interface
276276
277277 type
278278 TSingleton = class
279279 name: String;
280280 constructor create;
281281 end;
282282
283283 implementation
284284
285285 var
286286 Singleton: TSingleton = nil;
287287
288288 constructor TSingleton.Create;
289289 begin
290290 if not(assigned(Singleton)) then begin
291291 inherited;
292292 (*... do initializations ...*)
293293 Singleton := self;
294294 end else begin
295295 self := Singleton;
296296 end;
297297 end;
298298
299299 end.
300300```
301301
302302In the *Singleton1* unit, notice the following:
303303
304304- The Singleton variable is defined in the **implementation** section. This makes the variable invisible outside the unit.
305305- A public constructor is used.
306306
307307Free 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.
308308
309309## Why It Is Different In Pascal
310310
311311Then why not implement the singleton just like it is shown in the Pattern diagram? Well, here we go:
312312
313313``` pascal
314314unit Singleton2;
315315
316316 {$mode objfpc}{$H+}
317317
318318 interface
319319
320320 uses
321321 Classes, SysUtils;
322322
323323 type
324324 TSingleton = class
325325 private
326326 constructor Create;
327327 public
328328 name: String;
329329 class function GetInstance : TSingleton;
330330 end;
331331
332332 implementation
333333 var
334334 Singleton : TSingleton = nil;
335335
336336 constructor TSingleton.Create;
337337 begin
338338 inherited Create;
339339 end;
340340
341341 class function TSingleton.GetInstance : TSingleton;
342342 begin
343343 if Singleton = nil then
344344 Singleton := TSingleton.Create;
345345 Result := Singleton;
346346 end;
347347
348348 end.
349349```
350350
351351The problem with the *Singleton2* unit is that the program will work with the following client code:
352352
353353``` pascal
354354program TrueSingleton;
355355
356356 {$mode objfpc}{$H+}
357357
358358 uses
359359 {$IFDEF UNIX}{$IFDEF UseCThreads}
360360 cthreads,
361361 {$ENDIF}{$ENDIF}
362362 Classes, Singleton2
363363 { you can add units after this };
364364
365365 {$R TrueSingleton.res}
366366 var
367367 s1, s2: TSingleton;
368368
369369 begin
370370 s1:= TSingleton.Create;
371371 s1.name := 'one';
372372 writeln('name of s1: '+s1.name);
373373
374374 s2:= TSingleton.Create;
375375 s2.name := 'two';
376376
377377 writeln('name of s1: '+s1.name);
378378 writeln('name of s2: '+s2.name);
379379 //writeln('name of singleton: ' + Singleton.name);
380380 readln;
381381 end.
382382```
383383
384384It 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.
385385
386386## The 'constructor should be public' Singleton
387387
388388A *small* change makes a big difference:
389389
390390``` pascal
391391unit Singleton3;
392392
393393 {$mode objfpc}{$H+}
394394
395395 interface
396396
397397 uses
398398 Classes, SysUtils;
399399
400400 type
401401 TSingleton = class
402402 private
403403 constructor Init;
404404 public
405405 name: String;
406406 class function Create: TSingleton;
407407 end;
408408
409409 implementation
410410 var
411411 Singleton : TSingleton = nil;
412412
413413 constructor TSingleton.Init;
414414 begin
415415 inherited Create;
416416 end;
417417
418418 class function TSingleton.Create: TSingleton;
419419 begin
420420 if Singleton = nil then
421421 Singleton := TSingleton.Init;
422422 Result := Singleton;
423423 end;
424424
425425 end.
426426```
427427
428428The *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:
429429
430430``` pascal
431431program TrueSingleton;
432432
433433 {$mode objfpc}{$H+}
434434
435435 uses
436436 {$IFDEF UNIX}{$IFDEF UseCThreads}
437437 cthreads,
438438 {$ENDIF}{$ENDIF}
439439 Classes, Singleton3
440440 { you can add units after this };
441441
442442 {$R TrueSingleton.res}
443443 var
444444 s1, s2: TSingleton;
445445
446446 begin
447447 s1:= TSingleton.Create;
448448 s1.name := 'one';
449449 writeln('name of s1: '+s1.name);
450450
451451 s2:= TSingleton.Create;
452452 s2.name := 'two';
453453
454454 writeln('name of s1: '+s1.name);
455455 writeln('name of s2: '+s2.name);
456456 //writeln('name of singleton: ' + Singleton.name);
457457 readln;
458458 end.
459459```
460460
461461Notice 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.
462462
463463## Hide That For Me
464464
465465When 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.}
466466
467467# Discussion Of The Options
468468
469469In this part we will pay attention to some of the discussions.
470470
471471## Reducing the visibility of the constructor
472472
473473Of 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:
474474
475475`The reason you can't lower the visibility of the constructor or any`\
476476`method for that matter... A class interface (implementation section) ,`\
477477`even for TObject as in your example, is a contract of how you can use`\
478478`that class and what is available to you.  By lowering the visibility`\
479479`of a method or constructor in a descendant class, you are breaking the`\
480480`contract previously defined. This is a BIG no-no, hence the reason it`\
481481`is not allowed.`
482482
483483## Design Time Help vs. Run Time Breaking
484484
485485The following arguments may lead you to choose the Singleton3 unit as example implementation:
486486
487487- 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.
488488- If you want to avoid multiple instantiation of the class, then why not provide design time help to the client programmer.
489489- In other programming languages it is not bad programming behavior, so FreePascal must have a very good reason to avoid it.
490490- Reducing the visibility of any method of a class should not be allowed except for the constructor.
491491
492492## The pattern is not followed
493493
494494Yes, 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:
495495
496496- The intent of the pattern is followed and the benefits achieved.
497497- 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.
498498- Some compromises had to be made to make the singleton work in FreePascal.
499499
500500## The implementations have a problem with multi-threading and synchronization
501501
502502I 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.
503503
504504## The singleton class implementation has a problem with platform independence
505505
506506A 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.
507507
508508# Conclusion
509509
510510Yes, 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.
511511
512512---
513513*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).*
514514Category: Design Patterns
515515Category: FPC
516516Category: Pascal
517517Category: Tutorials

Back to history