You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
finding an appropriate provider while hiding both the provider’s
116
116
concrete type and the process used to locate it.</p>
117
117
<h2><ahref="#when-to-use-it" name="when-to-use-it">When to Use It</a></h2>
118
-
<p>If a large number of places in the codebase need access to the same
119
-
object and there isn’t an obvious way for them to get it, this pattern
120
-
is often a good solution. It’s usually more flexible than a static
121
-
class, and more maintainable than a <aclass="gof-pattern"
122
-
href="singleton.html">Singleton</a>.</p>
123
-
<p>One limitation is that the implementation of the service doesn’t know
124
-
<em>who</em> is using it or what for. This means it must be able to work
125
-
correctly in any circumstance. For example, a class that expects to
126
-
only be used during the simulation portion of the game loop and not
127
-
during rendering may not work as a service — it wouldn’t be able
128
-
to ensure that it’s being used at the right time. So, if our class
129
-
only expects to be used within a certain context, it may be safest to
130
-
avoid exposing it to the world with this pattern.</p>
118
+
<p>Anytime you make something globally accessible to every part of your program,
119
+
you’re asking for trouble. That’s the main problem with the
120
+
<aclass="gof-pattern" href="singleton.html">Singleton</a> pattern, and this
121
+
pattern is no different. My simplest advice for when to use a service locator
122
+
is: <em>sparingly</em>.</p>
123
+
<p>Instead of using a global mechanism to give some code access to an
124
+
object it needs, first consider <em>just passing the object to it</em>. That’s dead
125
+
simple, and it makes the coupling completely obvious. That will cover most of
126
+
your needs.</p>
127
+
<p><em>But…</em> there are some times when manually passing around an object is
128
+
gratuitous or actively makes code harder to read. Some systems, like logging
129
+
or memory management, shouldn’t be part of a module’s public API. The
130
+
parameters to your rendering code should have to do with <em>rendering</em>, not
131
+
stuff like logging.</p>
132
+
<p>Likewise, other systems represent facilities that are fundamentally singular
133
+
in nature. Your game probably only has one audio device or display system
134
+
that it can talk to. It is an ambient property of the environment, so plumbing
135
+
it through ten layers of methods just so one deeply nested call can get to it
136
+
is adding needless complexity to your code.</p>
137
+
<p>In those kinds of cases, this pattern can help. As we’ll see, it functions
138
+
as a more flexible, more configurable cousin of the singleton. When used
139
+
well, it can make your codebase more flexible with little runtime cost.</p>
131
140
<h2><ahref="#keep-in-mind" name="keep-in-mind">Keep in Mind</a></h2>
132
-
<h3><ahref="#the-service-is-globally-accessible" name="the-service-is-globally-accessible">The service is globally accessible</a></h3>
133
-
<p>This pattern shares a problem with the classic <aclass="gof-pattern"
134
-
href="singleton.html">Singleton</a> pattern: it’s <em>global.</em> This is
135
-
convenient for code that needs the service, but opens the door to
136
-
coupling and maintenance headaches if the wrong code starts using the
137
-
service.</p>
141
+
<h3><ahref="#the-service-doesn’t-know-who-is-locating-it" name="the-service-doesn’t-know-who-is-locating-it">The service doesn’t know who is locating it</a></h3>
142
+
<p>Since the locator is globally accessible, any code in the game could be
143
+
requesting a service and then poking at it. This means that service must
144
+
be able to work correctly in any circumstance. For example, a class that
145
+
expects to only be used during the simulation portion of the game loop
146
+
and not during rendering may not work as a service — it wouldn’t be able
147
+
to ensure that it’s being used at the right time. So, if a class
148
+
expects to only be used in a certain context, it’s safest to
149
+
avoid exposing it to the entire world with this pattern.</p>
138
150
<h3><ahref="#the-service-actually-has-to-be-located" name="the-service-actually-has-to-be-located">The service actually has to be located</a></h3>
139
151
<p>With a Singleton or a static class, there’s no chance for the instance
140
152
we need to <em>not</em> be available. Calling code can take for granted that
@@ -191,8 +203,8 @@ <h3><a href="#the-service-provider" name="the-service-provider">The service prov
191
203
<p>Now we have an interface and an implementation. The remaining piece is
192
204
the service locator — the class that ties the two together.</p>
0 commit comments