-
Notifications
You must be signed in to change notification settings - Fork 513
Expand file tree
/
Copy pathsingleton.html
More file actions
708 lines (662 loc) · 50.8 KB
/
singleton.html
File metadata and controls
708 lines (662 loc) · 50.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Singleton · Design Patterns Revisited · Game Programming Patterns</title>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="style.css" />
<link href="https://fonts.googleapis.com/css?family=Merriweather:400,400italic,700,700italic|Source+Code+Pro|Source+Sans+Pro:200,300,400,600,400italic,600italic|Rock+Salt" rel="stylesheet" type="text/css">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-42804721-1', 'gameprogrammingpatterns.com');
ga('send', 'pageview');
</script>
<script src="jquery-3.6.0.min.js"></script>
<script src="script.js"></script>
</head>
<body id="top">
<div class="page sidebar">
<span class="theme-toggler" title="dark theme" onclick="toggleTheme()"></span>
<div class="content">
<nav class="top">
<span class="prev">← <a href="prototype.html">Previous Chapter</a></span>
<span class="next"><a href="state.html">Next Chapter</a> →</span>
<span class="toc">≡ <a href="/">The Book</a></span>
</nav>
<h1>Singleton</h1>
<h1 class="book"><a href="/">Game Programming Patterns</a><span class="section"><a href="design-patterns-revisited.html">Design Patterns Revisited</a></span></h1>
<p>This chapter is an anomaly. Every other chapter in this book shows
you how to use a design pattern. This chapter shows you how <em>not</em> to use
one.</p>
<p>Despite noble intentions, the <a class="gof-pattern"
href="http://c2.com/cgi/wiki?SingletonPattern">Singleton</a> pattern described
by the Gang of Four usually does more harm than good. They stress that the
pattern should be used sparingly, but that message was often lost in translation
to the <span name="instance">game industry</span>.</p>
<p>Like any pattern, using Singleton where it doesn’t belong is about as helpful as
treating a bullet wound with a splint. Since it’s so overused, most of this
chapter will be about <em>avoiding</em> singletons, but first, let’s go over the
pattern itself.</p>
<aside name="instance">
<p>When much of the industry moved to object-oriented programming from C, one
problem they ran into was “how do I get an instance?” They had some method they
wanted to call but didn’t have an instance of the object that provides that
method in hand. Singletons (in other words, making it global) were an easy way
out.</p>
</aside>
<h2><a href="#the-singleton-pattern" name="the-singleton-pattern">The Singleton Pattern</a></h2>
<p><em>Design Patterns</em> summarizes Singleton like this:</p>
<blockquote>
<p>Ensure a class has one instance, and provide a global point of access to it.</p>
</blockquote>
<p>We’ll split that at “and” and consider each half separately.</p>
<h3><a href="#restricting-a-class-to-one-instance" name="restricting-a-class-to-one-instance">Restricting a class to one instance</a></h3>
<p>There are times when a class cannot perform correctly if there is more than one
instance of it. The common case is when the class interacts with an external
system that maintains its own global state.</p>
<p>Consider a class that wraps an underlying file system API. Because file
operations can take a while to complete, our class performs operations
asynchronously. This means multiple operations can be running concurrently, so
they must be coordinated with each other. If we start one call to create a file
and another one to delete that same file, our wrapper needs to be aware of both
to make sure they don’t interfere with each other.</p>
<p>To do this, a call into our wrapper needs to have access to every previous
operation. If users could freely create instances of our class, one instance
would have no way of knowing about operations that other instances started.
Enter the singleton. It provides a way for a class to ensure at compile time
that there is only a single instance of the class.</p>
<h3><a href="#providing-a-global-point-of-access" name="providing-a-global-point-of-access">Providing a global point of access</a></h3>
<p>Several different systems in the game will use our file system wrapper: logging,
content loading, game state saving, etc. If those systems can’t create their own
instances of our file system wrapper, how can they get ahold of one?</p>
<p>Singleton provides a solution to this too. In addition to creating the single
instance, it also provides a globally available method to get it. This way,
anyone anywhere can get their paws on our blessed instance. All together, the
classic implementation looks like this:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">static</span> <span class="n">FileSystem</span><span class="o">&</span> <span class="n">instance</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// Lazy initialize.</span>
<span class="k">if</span> <span class="p">(</span><span class="n">instance_</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="n">instance_</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileSystem</span><span class="p">();</span>
<span class="k">return</span> <span class="o">*</span><span class="n">instance_</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="k">static</span> <span class="n">FileSystem</span><span class="o">*</span> <span class="n">instance_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>The static <code>instance_</code> member holds an instance of the class, and the private
constructor ensures that it is the <em>only</em> one. The public static <code>instance()</code>
method grants access to the instance from anywhere in the codebase. It is also
responsible for instantiating the singleton instance lazily the first time
someone asks for it.</p>
<p>A modern take looks like this:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">static</span> <span class="n">FileSystem</span><span class="o">&</span> <span class="n">instance</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">static</span> <span class="n">FileSystem</span> <span class="o">*</span><span class="n">instance</span> <span class="o">=</span> <span class="k">new</span> <span class="n">FileSystem</span><span class="p">();</span>
<span class="k">return</span> <span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="p">};</span>
</code></pre></div>
<p>C++11 <span name="thread">mandates</span> that the initializer for a local
static variable is only run once, even in the presence of concurrency. So,
assuming you’ve got a modern C++ compiler, this code is thread-safe where the
first example is not.</p>
<aside name="thread">
<p>Of course, the thread-safety of your singleton class itself is an entirely
different question! This just ensures that its <em>initialization</em> is.</p>
</aside>
<h2><a href="#why-we-use-it" name="why-we-use-it">Why We Use It</a></h2>
<p>It seems we have a winner. Our file system wrapper is available wherever we need
it without the tedium of passing it around everywhere. The class itself cleverly
ensures we won’t make a mess of things by instantiating a couple of instances.
It’s got some other nice features too:</p>
<ul>
<li>
<p><strong>It doesn’t create the instance if no one uses it.</strong> Saving memory and CPU
cycles is always good. Since the singleton is initialized only when it’s
first accessed, it won’t be instantiated at all if the game never asks for
it.</p>
</li>
<li>
<p><strong>It’s initialized at runtime.</strong> A common alternative to Singleton is a
class with static member variables. I like simple solutions, so I use static
classes instead of singletons when possible, but there’s one limitation
static members have: automatic initialization. The compiler initializes
statics before <code>main()</code> is called. This means they can’t use information
known only once the program is up and running (for example, configuration
loaded from a file). It also means they can’t reliably depend on each other
 — the compiler does not guarantee the order in which statics are
initialized relative to each other.</p>
<p>Lazy initialization solves both of those problems. The singleton will be
initialized as late as possible, so by that time any information it needs
should be available. As long as they don’t have circular dependencies, one
singleton can even refer to another when initializing itself.</p>
</li>
<li>
<p><strong>You can subclass the singleton.</strong> This is a powerful but often overlooked
capability. Let’s say we need our file system wrapper to be cross-platform.
To make this work, we want it to be an abstract interface for a file system
with subclasses that implement the interface for each platform. Here is the
base class:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">virtual</span> <span class="o">~</span><span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="k">virtual</span> <span class="kt">char</span><span class="o">*</span> <span class="n">readFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">virtual</span> <span class="kt">void</span> <span class="nf">writeFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">contents</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>Then we define derived classes for a couple of platforms:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">PS3FileSystem</span> <span class="o">:</span> <span class="k">public</span> <span class="n">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">virtual</span> <span class="kt">char</span><span class="o">*</span> <span class="n">readFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Use Sony file IO API...</span>
<span class="p">}</span>
<span class="k">virtual</span> <span class="kt">void</span> <span class="n">writeFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">contents</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Use sony file IO API...</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">class</span> <span class="nc">WiiFileSystem</span> <span class="o">:</span> <span class="k">public</span> <span class="n">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">virtual</span> <span class="kt">char</span><span class="o">*</span> <span class="n">readFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Use Nintendo file IO API...</span>
<span class="p">}</span>
<span class="k">virtual</span> <span class="kt">void</span> <span class="n">writeFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">contents</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Use Nintendo file IO API...</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<p>Next, we turn <code>FileSystem</code> into a singleton:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">static</span> <span class="n">FileSystem</span><span class="o">&</span> <span class="n">instance</span><span class="p">();</span>
<span class="k">virtual</span> <span class="o">~</span><span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="k">virtual</span> <span class="kt">char</span><span class="o">*</span> <span class="n">readFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">virtual</span> <span class="kt">void</span> <span class="nf">writeFile</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">path</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">contents</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">protected</span><span class="o">:</span>
<span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="p">};</span>
</code></pre></div>
<p>The clever part is how the instance is created:</p>
<div class="codehilite"><pre><span></span><code><span class="n">FileSystem</span><span class="o">&</span> <span class="nf">FileSystem::instance</span><span class="p">()</span>
<span class="p">{</span>
<span class="cp">#if PLATFORM == PLAYSTATION3</span>
<span class="k">static</span> <span class="n">FileSystem</span> <span class="o">*</span><span class="n">instance</span> <span class="o">=</span> <span class="k">new</span> <span class="n">PS3FileSystem</span><span class="p">();</span>
<span class="cp">#elif PLATFORM == WII</span>
<span class="k">static</span> <span class="n">FileSystem</span> <span class="o">*</span><span class="n">instance</span> <span class="o">=</span> <span class="k">new</span> <span class="n">WiiFileSystem</span><span class="p">();</span>
<span class="cp">#endif</span>
<span class="k">return</span> <span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>With a simple compiler switch, we bind our file system wrapper to the
appropriate concrete type. Our entire codebase can access the file system
using <code>FileSystem::instance()</code> without being coupled to any
platform-specific code. That coupling is instead encapsulated within the
implementation file for the <code>FileSystem</code> class itself.</p>
</li>
</ul>
<p>This takes us about as far as most of us go when it comes to solving a problem
like this. We’ve got a file system wrapper. It works reliably. It’s available
globally so every place that needs it can get to it. It’s time to check in the
code and celebrate with a tasty beverage.</p>
<h2><a href="#why-we-regret-using-it" name="why-we-regret-using-it">Why We Regret Using It</a></h2>
<p>In the short term, the Singleton pattern is relatively benign. Like many design
choices, we pay the cost in the long term. Once we’ve cast a few unnecessary
singletons into cold hard code, here’s the trouble we’ve bought ourselves:</p>
<h3><a href="#it's-a-global-variable" name="it's-a-global-variable">It’s a global variable</a></h3>
<p>When games were still written by a couple of guys in a garage, pushing the
hardware was more important than ivory-tower software engineering principles.
Old-school C and assembly coders used globals and statics without any trouble
and shipped good games. As games got bigger and more complex, architecture and
maintainability started to become the bottleneck. We struggled to ship games not
because of hardware limitations, but because of <em>productivity</em> limitations.</p>
<p>So we moved to languages like C++ and started applying some of the hard-earned
wisdom of our software engineer forebears. One lesson we learned is that global
variables are bad for a variety of reasons:</p>
<ul>
<li>
<p><strong>They make it harder to reason about code.</strong> Say we’re tracking down a bug
in a function someone else wrote. If that function doesn’t touch any global
state, we can wrap our heads around it just by understanding the body of the
<span name="pure">function</span> and the arguments being passed to it.</p>
<aside name="pure">
<p>Computer scientists call functions that don’t access or modify global state
“pure” functions. Pure functions are easier to reason about, easier for the
compiler to optimize, and let you do neat things like memoization where you
cache and reuse the results from previous calls to the function.</p>
<p>While there are challenges to using purity exclusively, the benefits are
enticing enough that computer scientists have created languages like Haskell
that <em>only</em> allow pure functions.</p>
</aside>
<p>Now, imagine right in the middle of that function is a call to
<code>SomeClass::getSomeGlobalData()</code>. To figure out what’s going on, we have
to hunt through the entire codebase to see what touches that global data.
You don’t really hate global state until you’ve had to <code>grep</code> a million
lines of code at three in the morning trying to find the one errant call
that’s setting a static variable to the wrong value.</p>
</li>
<li>
<p><strong>They encourage coupling.</strong> The new coder on your team isn’t familiar with
your game’s beautifully maintainable loosely coupled architecture, but he’s
just been given his first task: make boulders play sounds when they crash
onto the ground. You and I know we don’t want the physics code to be coupled
to <em>audio</em> of all things, but he’s just trying to get his task done.
Unfortunately for us, the instance of our <code>AudioPlayer</code> is globally visible.
So, one little <code>#include</code> later, and our new guy has compromised a carefully
constructed architecture.</p>
<p>Without a global instance of the audio player, even if he <em>did</em> <code>#include</code>
the header, he still wouldn’t be able to do anything with it. That
difficulty sends a clear message to him that those two modules should not
know about each other and that he needs to find another way to solve his
problem. <em>By controlling access to instances, you control coupling.</em></p>
</li>
<li>
<p><strong>They aren’t concurrency-friendly.</strong> The days of games running on a simple
single-core CPU are pretty much over. Code today must at the very least
<em>work</em> in a multi-threaded way even if it doesn’t take full advantage of
concurrency. When we make something global, we’ve created a chunk of memory
that every thread can see and poke at, whether or not they know what other
threads are doing to it. That path leads to deadlocks, race conditions, and
other hell-to-fix thread-synchronization bugs.</p>
</li>
</ul>
<p>Issues like these are enough to scare us away from declaring a global variable,
and thus the Singleton pattern too, but that still doesn’t tell us how we
<em>should</em> design the game. How do you architect a game without global state?</p>
<p>There are some extensive answers to that question (most of this book in many
ways <em>is</em> an answer to just that), but they aren’t apparent or easy to come by.
In the meantime, we have to get games out the door. The Singleton pattern looks
like a panacea. It’s in a book on object-oriented design patterns, so it <em>must</em>
be architecturally sound, right? And it lets us design software the way we have
been doing for years.</p>
<p>Unfortunately, it’s more placebo than cure. If you scan the list of problems
that globals cause, you’ll notice that the Singleton pattern doesn’t solve any
of them. That’s because a singleton <em>is</em> global state — it’s just encapsulated in a
class.</p>
<h3><a href="#it-solves-two-problems-even-when-you-just-have-one" name="it-solves-two-problems-even-when-you-just-have-one">It solves two problems even when you just have one</a></h3>
<p>The word “and” in the Gang of Four’s description of Singleton is a bit strange.
Is this pattern a solution to one problem or two? What if we have only one of
those? Ensuring a single instance is useful, but who says we want to let
<em>everyone</em> poke at it? Likewise, global access is convenient, but that’s true
even for a class that allows multiple instances.</p>
<p>The latter of those two problems, convenient access, is almost always why we
turn to the Singleton pattern. Consider a logging class. Most modules in the
game can benefit from being able to log diagnostic information. However, passing
an instance of our <code>Log</code> class to every single function clutters the method
signature and distracts from the intent of the code.</p>
<p>The obvious fix is to make our <code>Log</code> class a singleton. Every function can then
go straight to the class itself to get an instance. But when we do that, we
inadvertently acquire a strange little restriction. All of a sudden, we can no
longer create more than one logger.</p>
<p>At first, this isn’t a problem. We’re writing only a single log file, so we only
need one instance anyway. Then, deep in the development cycle, we run into
trouble. Everyone on the team has been using the logger for their own
diagnostics, and the log file has become a massive dumping ground. Programmers
have to wade through pages of text just to find the one entry they care about.</p>
<p>We’d like to fix this by partitioning the logging into multiple files. To do
this, we’ll have separate loggers for different game <span
name="worse">domains</span>: online, UI, audio, gameplay. But we can’t. Not only
does our <code>Log</code> class no longer allow us to create multiple instances, that
design limitation is entrenched in every single call site that uses it:</p>
<div class="codehilite"><pre><span></span><code><span class="nt">Log</span><span class="p">::</span><span class="nd">instance</span><span class="o">()</span><span class="p">.</span><span class="nc">write</span><span class="o">(</span><span class="s2">"Some event."</span><span class="o">);</span>
</code></pre></div>
<p>In order to make our <code>Log</code> class support multiple instantiation (like it
originally did), we’ll have to fix both the class itself and every line of code
that mentions it. Our convenient access isn’t so convenient anymore.</p>
<aside name="worse">
<p>It could be even worse than this. Imagine your <code>Log</code> class is in a library being
shared across several <em>games</em>. Now, to change the design, you’ll have to
coordinate the change across several groups of people, most of whom have neither
the time nor the motivation to fix it.</p>
</aside>
<h3><a href="#lazy-initialization-takes-control-away-from-you" name="lazy-initialization-takes-control-away-from-you">Lazy initialization takes control away from you</a></h3>
<p>In the desktop PC world of virtual memory and soft performance requirements,
lazy initialization is a smart trick. Games are a different animal. Initializing
a system can take time: allocating memory, loading resources, etc. If
initializing the audio system takes a few hundred milliseconds, we need to
control when that’s going to happen. If we let it lazy-initialize itself the
first time a sound plays, that could be in the middle of an action-packed part
of the game, causing visibly dropped frames and stuttering gameplay.</p>
<p>Likewise, games generally need to closely control how memory is laid out in the
heap to avoid <span name="fragment">fragmentation</span>. If our audio
system allocates a chunk of heap when it initializes, we want to know <em>when</em>
that initialization is going to happen, so that we can control <em>where</em> in the
heap that memory will live.</p>
<aside name="fragment">
<p>See <a class="pattern" href="object-pool.html">Object Pool</a> for a detailed
explanation of memory fragmentation.</p>
</aside>
<p>Because of these two problems, most games I’ve seen don’t rely on lazy
initialization. Instead, they implement the Singleton pattern like this:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">static</span> <span class="n">FileSystem</span><span class="o">&</span> <span class="n">instance</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">instance_</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="n">FileSystem</span><span class="p">()</span> <span class="p">{}</span>
<span class="k">static</span> <span class="n">FileSystem</span> <span class="n">instance_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>That solves the lazy initialization problem, but at the expense of discarding
several singleton features that <em>do</em> make it better than a raw global variable.
With a static instance, we can no longer use polymorphism, and the class must be
constructible at static initialization time. Nor can we free the memory that the
instance is using when not needed.</p>
<p>Instead of creating a singleton, what we really have here is a simple static
class. That isn’t necessarily a bad thing, but if a static class is all you
need, <span name="static">why not</span> get rid of the <code>instance()</code> method
entirely and use static functions instead? Calling <code>Foo::bar()</code> is simpler than
<code>Foo::instance().bar()</code>, and also makes it clear that you really are dealing
with static memory.</p>
<aside name="static">
<p>The usual argument for choosing singletons over static classes is that if you
decide to change the static class into a non-static one later, you’ll need to
fix every call site. In theory, you don’t have to do that with singletons
because you could be passing the instance around and calling it like a normal
instance method.</p>
<p>In practice, I’ve never seen it work that way. Everyone just does
<code>Foo::instance().bar()</code> in one line. If we changed Foo to not be a
singleton, we’d still have to touch every call site. Given that, I’d rather have
a simpler class and a simpler syntax to call into it.</p>
</aside>
<h2><a href="#what-we-can-do-instead" name="what-we-can-do-instead">What We Can Do Instead</a></h2>
<p>If I’ve accomplished my goal so far, you’ll think twice before you pull
Singleton out of your toolbox the next time you have a problem. But you still
have a problem that needs solving. What tool <em>should</em> you pull out? Depending on
what you’re trying to do, I have a few options for you to consider, but first…</p>
<h3><a href="#see-if-you-need-the-class-at-all" name="see-if-you-need-the-class-at-all">See if you need the class at all</a></h3>
<p>Many of the singleton classes I see in games are “managers” — those nebulous
classes that exist just to babysit other objects. I’ve seen codebases where it
seems like <em>every</em> class has a manager: Monster, MonsterManager, Particle,
ParticleManager, Sound, SoundManager, ManagerManager. Sometimes, for variety,
they’ll throw a “System” or “Engine” in there, but it’s still the same idea.</p>
<p>While caretaker classes are sometimes useful, often they just reflect
unfamiliarity with OOP. Consider these two contrived classes:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">Bullet</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="kt">int</span> <span class="n">getX</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x_</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">int</span> <span class="n">getY</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">y_</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">void</span> <span class="n">setX</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="n">x_</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="kt">void</span> <span class="n">setY</span><span class="p">(</span><span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="n">y_</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="kt">int</span> <span class="n">x_</span><span class="p">,</span> <span class="n">y_</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">class</span> <span class="nc">BulletManager</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">Bullet</span><span class="o">*</span> <span class="n">create</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Bullet</span><span class="o">*</span> <span class="n">bullet</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Bullet</span><span class="p">();</span>
<span class="n">bullet</span><span class="o">-></span><span class="n">setX</span><span class="p">(</span><span class="n">x</span><span class="p">);</span>
<span class="n">bullet</span><span class="o">-></span><span class="n">setY</span><span class="p">(</span><span class="n">y</span><span class="p">);</span>
<span class="k">return</span> <span class="n">bullet</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">bool</span> <span class="n">isOnScreen</span><span class="p">(</span><span class="n">Bullet</span><span class="o">&</span> <span class="n">bullet</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">bullet</span><span class="p">.</span><span class="n">getX</span><span class="p">()</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span>
<span class="n">bullet</span><span class="p">.</span><span class="n">getX</span><span class="p">()</span> <span class="o"><</span> <span class="n">SCREEN_WIDTH</span> <span class="o">&&</span>
<span class="n">bullet</span><span class="p">.</span><span class="n">getY</span><span class="p">()</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span>
<span class="n">bullet</span><span class="p">.</span><span class="n">getY</span><span class="p">()</span> <span class="o"><</span> <span class="n">SCREEN_HEIGHT</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">move</span><span class="p">(</span><span class="n">Bullet</span><span class="o">&</span> <span class="n">bullet</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">bullet</span><span class="p">.</span><span class="n">setX</span><span class="p">(</span><span class="n">bullet</span><span class="p">.</span><span class="n">getX</span><span class="p">()</span> <span class="o">+</span> <span class="mi">5</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<p>Maybe this example is a bit dumb, but I’ve seen plenty of code that reveals a
design just like this after you scrape away the crusty details. If you look at
this code, it’s natural to think that <code>BulletManager</code> should be a singleton. After
all, anything that has a <code>Bullet</code> will need the manager too, and how many
instances of <code>BulletManager</code> do you need?</p>
<p>The answer here is <em>zero</em>, actually. Here’s how we solve the “singleton” problem
for our manager class:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">Bullet</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">Bullet</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="o">:</span> <span class="n">x_</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">y_</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="p">{}</span>
<span class="kt">bool</span> <span class="n">isOnScreen</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">x_</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">x_</span> <span class="o"><</span> <span class="n">SCREEN_WIDTH</span> <span class="o">&&</span>
<span class="n">y_</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">y_</span> <span class="o"><</span> <span class="n">SCREEN_HEIGHT</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">move</span><span class="p">()</span> <span class="p">{</span> <span class="n">x_</span> <span class="o">+=</span> <span class="mi">5</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="kt">int</span> <span class="n">x_</span><span class="p">,</span> <span class="n">y_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>There we go. No manager, no problem. Poorly designed singletons are often
“helpers” that add functionality to another class. If you can, just move all of
that behavior into the class it helps. After all, OOP is about letting objects
take care of themselves.</p>
<p>Outside of managers, though, there are other problems where we’d reach to
Singleton for a solution. For each of those problems, there are some alternative
solutions to consider.</p>
<h3><a href="#to-limit-a-class-to-a-single-instance" name="to-limit-a-class-to-a-single-instance">To limit a class to a single instance</a></h3>
<p>This is one half of what the Singleton pattern gives you. As in our file system
example, it can be critical to ensure there’s only a single instance of a class.
However, that doesn’t necessarily mean we also want to provide <em>public</em>,
<em>global</em> access to that instance. We may want to restrict access to certain
areas of the code or even make it <span name="wrapper">private</span> to a
single class. In those cases, providing a public global point of access weakens
the architecture.</p>
<aside name="wrapper">
<p>For example, we may be wrapping our file system wrapper inside <em>another</em> layer
of abstraction.</p>
</aside>
<p>We want a way to ensure single instantiation <em>without</em> providing global access.
There are a couple of ways to accomplish this. Here’s one:</p>
<p><span name="assert"></span></p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">FileSystem</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">FileSystem</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">assert</span><span class="p">(</span><span class="o">!</span><span class="n">instantiated_</span><span class="p">);</span>
<span class="n">instantiated_</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">~</span><span class="n">FileSystem</span><span class="p">()</span> <span class="p">{</span> <span class="n">instantiated_</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="k">static</span> <span class="kt">bool</span> <span class="n">instantiated_</span><span class="p">;</span>
<span class="p">};</span>
<span class="kt">bool</span> <span class="n">FileSystem</span><span class="o">::</span><span class="n">instantiated_</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
</code></pre></div>
<p>This class allows anyone to construct it, but it will assert and fail if you try to
construct more than one instance. As long as the right code creates the instance
first, then we’ve ensured no other code can either get at that instance or
create their own. The class ensures the single instantiation requirement it
cares about, but it doesn’t dictate how the class should be used.</p>
<aside name="assert">
<p>An <em>assertion</em> function is a way of embedding a contract into your code.
When <code>assert()</code> is called, it evaluates the expression passed to it. If it
evaluates to <code>true</code>, then it does nothing and lets the game continue. If it
evaluates to <code>false</code>, it immediately halts the game at that point. In a
debug build, it will usually bring up the debugger or at least print out the
file and line number where the assertion failed.</p>
<p>An <code>assert()</code> means, “I assert that this should always be true. If it’s not,
that’s a bug and I want to stop <em>now</em> so you can fix it.” This lets you
define contracts between regions of code. If a function asserts that one of
its arguments is not <code>NULL</code>, that says, “The contract between me and the
caller is that I will not be passed <code>NULL</code>.”</p>
<p>Assertions help us track down bugs as soon as the game does something
unexpected, not later when that error finally manifests as something
visibly wrong to the user. They are fences in your codebase, corralling bugs
so that they can’t escape from the code that created them.</p>
</aside>
<p>The downside with this implementation is that the check to prevent multiple
instantiation is only done at <em>runtime</em>. The Singleton pattern, in contrast,
guarantees a single instance at compile time by the very nature of the class’s
structure.</p>
<h3><a href="#to-provide-convenient-access-to-an-instance" name="to-provide-convenient-access-to-an-instance">To provide convenient access to an instance</a></h3>
<p>Convenient access is the main reason we reach for singletons. They make it easy
to get our hands on an object we need to use in a lot of different places. That
ease comes at a cost, though — it becomes equally easy to get our hands on the
object in places where we <em>don’t</em> want it being used.</p>
<p>The general rule is that we want variables to be as narrowly scoped as possible
while still getting the job done. The smaller the scope an object has, the fewer
places we need to keep in our head while we’re working with it. Before we take
the shotgun approach of a singleton object with <em>global</em> scope, let’s consider
other ways our codebase can get access to an object:</p>
<ul>
<li>
<p><strong>Pass it in.</strong> The <span name="di">simplest</span> solution, and often the
best, is to simply pass the object you need as an argument to the functions
that need it. It’s worth considering before we discard it as too cumbersome.</p>
<aside name="di">
<p>Some use the term “dependency injection” to refer to this. Instead of code
reaching <em>out</em> and finding its dependencies by calling into something
global, the dependencies are pushed <em>in</em> to the code that needs it through
parameters. Others reserve “dependency injection” for more complex ways of
providing dependencies to code.</p>
</aside>
<p>Consider a function for rendering objects. In order to render, it needs
access to an object that represents the graphics device and maintains the
render state. It’s very common to simply pass that in to all of the rendering
functions, usually as a parameter named something like <code>context</code>.</p>
<p>On the other hand, some objects don’t belong in the signature of a method.
For example, a function that handles AI may need to also write to a <span
name="aop">log file</span>, but logging isn’t its core concern. It would be
strange to see <code>Log</code> show up in its argument list, so for cases like that
we’ll want to consider other options.</p>
<aside name="aop">
<p>The term for things like logging that appear scattered throughout a codebase
is “cross-cutting concern”. Handling cross-cutting concerns gracefully is
a continuing architectural challenge, especially in statically typed
languages.</p>
<p><a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect-oriented
programming</a> was
designed to address these concerns.</p>
</aside>
</li>
<li>
<p><strong>Get it from the base class.</strong> Many game architectures have shallow but
wide inheritance hierarchies, often only one level deep. For example, you
may have a base <code>GameObject</code> class with derived classes for each enemy or
object in the game. With architectures like this, a large portion of the
game code will live in these “leaf” derived classes. This means that all
these classes already have access to the same thing: their <code>GameObject</code> base
class. We can use that to our advantage:</p>
<p><span name="gameobject"></span></p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">GameObject</span>
<span class="p">{</span>
<span class="k">protected</span><span class="o">:</span>
<span class="n">Log</span><span class="o">&</span> <span class="n">getLog</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">log_</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="k">static</span> <span class="n">Log</span><span class="o">&</span> <span class="n">log_</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">class</span> <span class="nc">Enemy</span> <span class="o">:</span> <span class="k">public</span> <span class="n">GameObject</span>
<span class="p">{</span>
<span class="kt">void</span> <span class="nf">doSomething</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">getLog</span><span class="p">().</span><span class="n">write</span><span class="p">(</span><span class="s">"I can log!"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div>
<p>This ensures nothing outside of <code>GameObject</code> has access to its <code>Log</code> object,
but every derived entity does using <code>getLog()</code>. This pattern of letting
derived objects implement themselves in terms of protected methods provided
to them is covered in the <a class="pattern"
href="subclass-sandbox.html">Subclass Sandbox</a> chapter.</p>
<aside name="gameobject">
<p>This raises the question, “how does <code>GameObject</code> get the <code>Log</code> instance?” A
simple solution is to have the base class simply create and own a static
instance.</p>
<p>If you don’t want the base class to take such an active role, you can
provide an initialization function to pass it in or use the <a
class="pattern" href="service-locator.html">Service Locator</a> pattern to
find it.</p>
</aside>
</li>
<li>
<p><strong>Get it from something already global.</strong> The goal of removing <em>all</em> global
state is admirable, but rarely practical. Most codebases will still have a
couple of globally available objects, such as a single <code>Game</code> or <code>World</code>
object representing the entire game state.</p>
<p>We can reduce the number of global classes by piggybacking on existing ones
like that. Instead of making singletons out of <code>Log</code>, <code>FileSystem</code>, and
<code>AudioPlayer</code>, do this:</p>
<div class="codehilite"><pre><span></span><code><span class="k">class</span> <span class="nc">Game</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">static</span> <span class="n">Game</span><span class="o">&</span> <span class="n">instance</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">instance_</span><span class="p">;</span> <span class="p">}</span>
<span class="c1">// Functions to set log_, et. al. ...</span>
<span class="n">Log</span><span class="o">&</span> <span class="n">getLog</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="n">log_</span><span class="p">;</span> <span class="p">}</span>
<span class="n">FileSystem</span><span class="o">&</span> <span class="n">getFileSystem</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="n">fileSystem_</span><span class="p">;</span> <span class="p">}</span>
<span class="n">AudioPlayer</span><span class="o">&</span> <span class="n">getAudioPlayer</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="n">audioPlayer_</span><span class="p">;</span> <span class="p">}</span>
<span class="k">private</span><span class="o">:</span>
<span class="k">static</span> <span class="n">Game</span> <span class="n">instance_</span><span class="p">;</span>
<span class="n">Log</span> <span class="o">*</span><span class="n">log_</span><span class="p">;</span>
<span class="n">FileSystem</span> <span class="o">*</span><span class="n">fileSystem_</span><span class="p">;</span>
<span class="n">AudioPlayer</span> <span class="o">*</span><span class="n">audioPlayer_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
<p>With this, only <code>Game</code> is globally available. Functions can get to the
other systems <span name="demeter">through</span> it:</p>
<div class="codehilite"><pre><span></span><code><span class="n">Game</span><span class="o">::</span><span class="n">instance</span><span class="p">().</span><span class="n">getAudioPlayer</span><span class="p">().</span><span class="n">play</span><span class="p">(</span><span class="n">VERY_LOUD_BANG</span><span class="p">);</span>
</code></pre></div>
<aside name="demeter">
<p>Purists will claim this violates the Law of Demeter. I claim that’s still
better than a giant pile of singletons.</p>
</aside>
<p>If, later, the architecture is changed to support multiple <code>Game</code> instances
(perhaps for streaming or testing purposes), <code>Log</code>, <code>FileSystem</code>, and
<code>AudioPlayer</code> are all unaffected — they won’t even know the difference. The
downside with this, of course, is that more code ends up coupled to <code>Game</code>
itself. If a class just needs to play sound, our example still requires it
to know about the world in order to get to the audio player.</p>
<p>We solve this with a hybrid solution. Code that already knows about <code>Game</code>
can simply access <code>AudioPlayer</code> directly from it. For code that doesn’t, we
provide access to <code>AudioPlayer</code> using one of the other options described
here.</p>
</li>
<li>
<p><strong>Get it from a Service Locator.</strong> So far, we’re assuming the global class
is some regular concrete class like <code>Game</code>. Another option is to define a
class whose sole reason for being is to give global access to objects. This
common pattern is called a <a class="pattern"
href="service-locator.html">Service Locator</a> and gets its own chapter.</p>
</li>
</ul>
<h2><a href="#what's-left-for-singleton" name="what's-left-for-singleton">What’s Left for Singleton</a></h2>
<p>The question remains, where <em>should</em> we use the real Singleton pattern?
Honestly, I’ve never used the full Gang of Four implementation in a game. To
ensure single instantiation, I usually simply use a static class. If that
doesn’t work, I’ll use a static flag to check at runtime that only one instance
of the class is constructed.</p>
<p>There are a couple of other chapters in this book that can also help here. The
<a class="pattern" href="subclass-sandbox.html">Subclass Sandbox</a> pattern
gives instances of a class access to some shared state without making it
globally available. The <a class="pattern" href="service-locator.html">Service
Locator</a> pattern <em>does</em> make an object globally available, but it gives you more
flexibility with how that object is configured.</p>
<nav>
<span class="prev">← <a href="prototype.html">Previous Chapter</a></span>
<span class="next"><a href="state.html">Next Chapter</a> →</span>
<span class="toc">≡ <a href="/">The Book</a></span>
</nav>
</div>
</div>
<footer>© 2009-2021 Robert Nystrom</footer>
</body>
</html>