Design Patterns: The Strategy Pattern

Have you guys played Pyre yet? No? Well do. It is one of my favourite games this year. It is also a sort of Strategy game… kind of… it is hard to define what it is really, but it has strategy elements!

In this post I am going to talk about the Strategy pattern. In wikipedia term, the Strategy pattern is a behavioural software design pattern that enables an algorithm’s behaviour to be selected at runtime. Fancy.

In game development terms, we could look at enemies. In an action game, maybe you want the enemies to have different behaviours when they fight the player. I am going to use like an Ace Combat style game as an example. Each Enemy Pilot has some standard stuff, but we want the pilot AI to do many different things. We could use the strategy pattern for this.

public class EnemyPilot
{
    .. Other code here
    private IPilotAI _pilotAI;
    void Update()
    {
         _pilotAI.Update();
    }
}

In the above C# code, I have a class that is the EnemyPilot that contains the IPilotAI interface that we can set at runtime. We can now make a number of AI behaviours that use the Pilot AI interface. This is much better than inheriting from the whole EnemyPilot class each time and we are encapsulating the only thing that varies, i.e. the Pilot AI. And really it as that. Cool huh?

Design Patterns – Observer

Today I am going to talk about the Observer Pattern. From Wikipedia once again:

“The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.”

In plain old English, the Observer pattern “Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified.”

What does this amount to in the real world. So you know when you sign up to one of those voucher code sites for a specifc type of voucher and you get a notification whenever there is a new voucher type available? That is basically the observer pattern.

In game development a common use case is an Achievement system. It is an example that has been used multiple times, but hey, if it ain’t broke, don’t fix it. In a game, there are Achievements that can be obtained through a variety of different methods. Maybe you are working on Final Fantasy 12 and want to add an achievement that the player gets for shouting they are Captain Basch 1000 times.

If we aren’t clever about how we design this system, we could have a crazy spaghetti like thing that is linked to every part of our code base. This is bad, as the likely hood of you breakign the achievement system if you make a change or vice versa is pretty high. Are you thinking about using a Singleton for this? DON’T. This is a prime example of where not to use a Singleton. We want our nice Achievement system all lumped in one place and we don’t want to tightly couple the system to every single part of the code base. This is where the Observer pattern comes in. The pattern allows one piece of code to announce something has happenned without actually giving a damn who recieves the notification.

Let’s look at some nice C# code. Essentilaly the code can be broken down into two parts. The Subject  and the Observer.

First we will take a look at the subject. The subject holds a list of all the observers interested in getting information ewhen something cool happens. When said something has happenned, it sends a notificaiton to all the observers.

public abstract class Subject
{
    List<IObserver> _observers = new List<Observers>();
    
    public void Notify()
    {
        _observers.ForEach(x => x.OnNotify());
    }

    public void AddObserver(Observer observer)
    {
        _observers.Add(observer);
    }
    public void RemoveObserver(Observer observer)
    {
        _observer.Remove(observer);
    }
}

And to reiterate somewhat, the Observers are the objects interested in doing something when the event happens.

public interface IObserver
{
    void OnNotify();
}

In fact rather than going into the previously mentioned Achievement system, I am going to talk about the “I’m Captian Basch” bit in FF12.

What I want is the NPCs in a certain area to see if they hear it and increase the notoriety. In the below code I have already added the NPCs as Observers from some other system.

public class BaschShouter : Subject
{
...
    private void OnShoutedImBasch()
    { 
        Notify();
    }
...
}

So every time the player refutes Ondore’s lies:

public class NPC : IObserver
{
     public void OnNotify()
     {
          if (NPCIsInEarShotOfPlayer())
          {
              DontBelieveOndoresLies();
          }
     }
}

You also may have some NPCs that are loyal and stop you shouting and you have also registered those:

public class NPCLoyalToOndore : IObserver 
{ 
    public void OnNotify() 
    { 
       if (NPCIsInEarShotOfPlayer())
       {
            ChastisePlayerForLyingAboutMyLeige();
       }
    } 
}

And there we have it. Observer pattern.

Design Patterns – Singleton

Have you player Nier: Automata yet? Do it! It is currently on my shortlist for my Game of the Year. Just not on PC, that version is… well.. broken… and will probably never be fix becasue budgets and game development.

Anyway, I want to talk about the Singleton pattern, a somewhat controversial pattern. Many people say it is overused and have various opinions why they are bad. I am probably going to get labeled as a paraiah for this and say they are not THAT bad, but can be abused. Many people consider it as an “anti-pattern”. On the flip side, I have worked in code bases that have gone to great lengths to avoid them and have actually just made the maintenance of the porject more of a pain than if the singleton pattern was used in a sensible way. In practice, like all design patterns, it is a programming technique that is part of your toolbox and you may find an ideal solution to use it! You may also find terrible ways to use it!

So firstly what IS the Singleton pattern?

Wikipedia tells us that:

“In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.”

In other words it “ensure a class has one instance, and provide a global point of access to it”.

OK, here is a real world example. Here in sunny England we have a Prime Minister. There can only be one PM of the country at a time. Whenever the PM needs to do something, the same PM is called. The PM is a singleton. Yeah, ok, not a great example because politics, but you get the idea. I prefer my Maccys example in the last post…

There are some genuine use cases for a singleton. These can include Input Systems and File Loading systems. These 2 examples in particular are good candidates for singletons as a lot of other areas of the code base will want to access them. They are also likely to maintain their own state. File Systems may be busy loading files asynchrounously and Input Systems are managing the state of the controllers. You don’t really want multiple instances of these guys. What is going to happen if you suddenly have 2 Input Systems? Which one do you pick?

It is worth noting that there can be several different “kinds” of singleton as well.

Ones that exist all the time:

public class Singleton<T> where T : class
    {
        private static readonly T _instance = Activator.CreateInstance(typeof(T)) as T;
        public static T Instance { get { return _instance; } }
    }

Some that are created when needed, saving memory if they are never called.

public abstract class LazySingleton<T> where T : class
{
       private static T _instance = null;
       public static T Instance
       {
            get
            {
              if (_instance == null)
              { 
                    _instance = Activator.CreateInstance(typeof(T)) as T;
              } 
              return _instance; 
            }
      }
}

And some explicit to working with Unity that I won’t go into here.

Like all design patterns, the Singleton is good at solving a certain type of problem.

However, as I mentioned they can cause issues. Yes, Singletons provide a nice point of access to a point in you program so you don’t have to pass refs to everything. However, the main porblem in my opinion is they encourage coupling. Now while not all coupling is bad, it can be from an architectural standpoint. For example, say you have a racing game that you have a beautifully architected so it is all loosely coupled. Inside is Audio Manager that has been made a Singleton. A brand new, fresh-out-of-uni grad joins your project and is given the task to make the cars make a horrible, expensive-souding crunch noise play when the cars collide. What does he do? He goes into the physics code and couples the audio to the physics. Architecture broken.

There are a lot of other reasons not to Singleton. If you used all the information provided when you type into google “why are singletons bad” you could write a whole book on the subject. They may have emerged from a book that was written in 1994, may not be thread safe, they can be misused, etc. But at the end of the day, they are a tool to solve certain problems. And to be honest, in the right scenarios they can be pretty good tools. Although it is nice to have a really beautiful, loosely coupled and architected system, this could be the most complex thing in the world you have to deal with and when it comes to actually getting stuff done, it could be a massive pain. Yes, bugs maybe harder to track down becasue of Singleton state, but hang on, if you architect them correctly they can perform a single point of contact for a certain system. Which if you find the bug is in that system, it is potentially easier to find?

Basically, although you will read every other book saying Singletons are bad, if you are smart with them, they can actually be pretty powerful tools. Also most of the arguments you will see are around OOP, and in games, there are reasons in 2017 not to go down the OOP route. I have also seen in my time “clever” OOP design make everything a hell of a lot more complicated to jsut get stuff done. In summary, like all patterns, Singletons are a tool, theya re good for some scenarios, but don;t right them off.

Until next time!