Reader small image

You're reading from  Game Development Patterns with Unity 2021 - Second Edition

Product typeBook
Published inJul 2021
Reading LevelBeginner
PublisherPackt
ISBN-139781800200814
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
David Baron
David Baron
author image
David Baron

David Baron is a game developer with over 15 years of experience in the industry. He has worked for some well-known AAA, mobile, and indie game studios in Montreal, Canada. His skill set includes programming, design, and 3D art. As a programmer, he has worked on various games for various platforms, including virtual reality, mobile, and consoles.
Read more about David Baron

Right arrow
Managing Dependencies with the Service Locator Pattern

This chapter will be brief because the Service Locator pattern we will review is simple and efficient. The core idea of this pattern is straightforward: it revolves around having a central registry of initialized dependencies. But to be more precise, these dependencies are components that offer specific services that we can expose with interfaces we call "service contracts". Hence, when a client needs to call upon a particular service, it doesn't need to know how to localize and initialize it; it just needs to ask the Service Locator pattern, and this will do all the legwork to fulfill the service contract.

As we will see in this chapter, it's quite a simple design and is easy to implement.

In this chapter, we will cover the following topics:

  • Understanding the Service Locator pattern
  • Implementing...

Technical requirements

The following chapter is hands-on, so you will need to have a basic understanding of Unity and C#.

We will be using the following Unity-specific engine and C# language concepts:

  • Statics
  • Generics

If unfamiliar with these concepts, please review Chapter 3A Short Primer to Programming in Unity.

The code files of this chapter can be found on GitHub, at https://github.com/PacktPublishing/Game-Development-Patterns-with-Unity-2021-Second-Edition/tree/main/Assets/Chapters/Chapter16.

Check out the following video to see the code in action: https://bit.ly/36AKWli

Static is a keyword modifier. A method declared as static in a class can be called without instantiating an object.  

Understanding the Service Locator pattern

Compared to more traditional patterns, the Service Locator pattern has less academic theory behind it and is very pragmatic in its overall design. As its name implies, its purpose is to locate services for a client. It achieves this by maintaining a central registry of objects that offer specific services.

Let's review a diagram of a typical Service Locator implementation:

Figure 16.1 – Diagram of the Service Locator pattern

As we can see, we could easily say that the Service Locator pattern is acting as a proxy between the clients (requestors) and the service providers, and this approach decouples them to a certain degree. A client will only need to call the Service Locator pattern when it has a dependency to resolve and needs access to a service. We could say that the Service Locator pattern is acting similarly to a waiter in a restaurant, taking orders from clients and acting as an intermediary between...

Benefits and drawbacks of the Service Locator pattern

Here are some of the potential benefits of using the Service Locator pattern:

  • Runtime optimization: The Service Locator pattern can optimize an application by dynamically detecting more optimized libraries or components to complete a specific service, depending on the runtime context.
  • Simplicity: Service Locator is one of the most straightforward dependency management patterns to implement and doesn't have the steep learning curve of a dependency injection (DI) framework. Hence, you can quickly start using it in a project or teach it to colleagues.

Here are some drawbacks of using the Service Locator pattern:

  • Black boxing: The Service Locator pattern's registry obfuscates class dependencies. Consequently, some issues might pop up at runtime instead of during compilation if dependencies are missing or incorrectly registered.
  • Globally dependent: If overly used and with the wrong intentions, the Service Locator pattern can...

When to use the Service Locator pattern

The question on when to use the Service Locator pattern is self-explanatory, based on its description. For example, if you have a list of services that you dynamically need to access but want to encapsulate the process involved in obtaining them, then this pattern can offer a solution.

But another aspect we should consider when contemplating using the Service Locator pattern is when not to use it. Because a Service Locator pattern is usually globally accessible, as its name implies, it should locate and provide access to services. Then, we should use it only to expose services that have a global scope.

For instance, we need to access the heads-up display (HUD) to update one of its user interface (UI) components. Should we consider the HUD a global service that should be accessible through the Service Locator pattern? The answer should be no, as the HUD only appears during certain parts of the game and should be accessible only by particular components...

Implementing a Service Locator pattern

We are going to implement a basic Service Locator pattern to expose three specific services, as follows:

  • Logger: A service that acts as a facade to a centralized logging system
  • Analytics: A service that sends custom analytical information to a backend to provide insight on player behavior
  • Advertisement: A service that pulls video advertisements (ads) from a network and displays them to monetize the game's content at specific moments

We are adding these services to the registry of the Service Locator pattern because of their following characteristics:

  • They offer a specific service.
  • They need to be accessible from anywhere in the code base.
  • They can be mocked or removed without causing any regression in the gameplay code.

As we are going to see from the following code example, implementing a basic Service Locator pattern is a straightforward process. These are the steps we'll take:

  1. Let's start by implementing the most...

Testing the Service Locator pattern

To test our implementation of the Service Locator pattern, let's write a client class that we will attach as a component to a GameObject in an empty Unity scene, as follows:

using UnityEngine;

namespace Chapter.ServiceLocator
{
public class ClientServiceLocator : MonoBehaviour
{
void Start() {
RegisterServices();
}

private void RegisterServices() {
ILoggerService logger = new Logger();
ServiceLocator.RegisterService(logger);

IAnalyticsService analytics = new Analytics();
ServiceLocator.RegisterService(analytics);

IAdvertisement advertisement = new Advertisement();
ServiceLocator.RegisterService(advertisement);
}

void OnGUI()
{
GUILayout.Label("Review output in the console:");

if
(GUILayout.Button("Log Event")) {
ILoggerService logger =
ServiceLocator...

Reviewing alternative solutions

If you are having issues with the management of dependencies in your code base, it might be time to start investigating the use of a DI framework. DI is a technique in which an object receives dependencies it needs through an "injection mechanism." There are several ways an object can receive its dependencies—through the constructor, a setter, or even with an interface that provides an injector method.

The best way to start using DI in a structured manner is through a framework because this gives you a helping hand in managing complex relationships between objects, the initialization process, and the lifespan of dependencies. In conclusion, you should start considering using a DI framework when you see tight coupling between classes and when their dependencies are becoming a bottleneck to writing consistent, testable, and maintainable code.

Extenject is a free DI framework for Unity that can be downloaded from the Asset Store:

https...

Summary

In this chapter, we reviewed the Service Locator pattern. This pattern is a simple solution to resolving a recurring challenge of managing dependencies between objects relying on services (functionalities) that other objects offer. In its simplest form, the Service Locator pattern decouples the relationship between a client (requester) and a service provider.

We have arrived at the end of our journey, as this is the last chapter of the book. We hope you enjoyed the content of each chapter. Please remember that the concepts presented throughout this book are just introductions, not the final word on the subject matter. There's a lot more to learn about design patterns, Unity, and game development—so much that we can't define it in a single book. Thus, we encourage you to continue learning, take what we reviewed together in each chapter, and make it better because there's always room for improvement.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Game Development Patterns with Unity 2021 - Second Edition
Published in: Jul 2021Publisher: PacktISBN-13: 9781800200814
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
David Baron

David Baron is a game developer with over 15 years of experience in the industry. He has worked for some well-known AAA, mobile, and indie game studios in Montreal, Canada. His skill set includes programming, design, and 3D art. As a programmer, he has worked on various games for various platforms, including virtual reality, mobile, and consoles.
Read more about David Baron