Patterns. Singleton, Strategy, Factory Method (Earth Must Be Destroyed)

 

Patterns. Singleton, Strategy, Factory Method (Earth Must Be Destroyed)

I figured it might be interesting to talk about software design patterns. Wait, don’t leave! The way I’m going to make it interesting is implement a few of them in a simple game. The implementations might be a bit ad hoc, but it’s always cooler to see something in a working project, instead of looking at dry example code that doesn’t do much.

This post covers three, I’ve picked two of them for no particular reason and the Singleton pattern just because it’s so widespread that I might as well get over with it now. More patterns to follow in the future.

What’s a Software Design Pattern?

It’s not really the point of this post to provide an in-depth explanation to what Software Design Patterns are, so I’ll keep it short. A pattern is a reusable solution to a common problem in software design. They’re meant to be general, and are, essentially, formalised recommendations and best practices. They’re not code.

For example, if you wanted to build a means of transportation from point A to B - you could come up with the way to design something all by yourself, or you could use a generalised description of, say, a bicycle. That description would suggest that bicycles usually have two wheels, a seat, a pair of pedals, a handle bar and breaks. The actual implementation - materials used, shapes, colours, number of gears, etc. - are up to you. And since patterns are basically just recommendations - you can still decide to ignore bits and pieces of it, making a bike with five wheels or no steering. Not sure I’m particularly good at analogies, let’s forget this paragraph ever happened and move on.

The Game

The game is as simple as it gets. There’s an Earth to the right of the screen, there’re two alien ships that the player can switch between, representing two great alien races - Cucumberians and Murderdevastators. Both ships have weapons, unfortunately for Murderdevastators - their ship has the weakest weapon, Cucumberians were pretty smart and invested in military research, their weapon is so much better.

A health bar is displayed at the top of the screen, representing the well-being of the planet. When the planet is destroyed - it changes color to a slightly darker shade (didn’t want to scare you, folks, by fancy hyper-realistic explosions and stuff).

The controls:

Switch between alien ships - ‘A’
Fly around - arrow keys
Fire a weapon - ‘Space’
Restart - ‘R’
Exit the game - ‘Escape’

If you want, you can check out the whole code. Look at it, run it, or feel free to play around with it.

Now, let’s get on with patterns.

Singleton

The pop-star of patterns, widely used and frequently critiqued for being misused.

The point of a singleton is that, very much like with highlanders, there can be only one. The constructor for a singleton is set to be private, so nothing can create it from outside the class. There’s a method for retrieving the only instance of it, and that’s pretty much all there is to it.

I figured, since our game has only one Earth - why not use the Singleton here.

	public final class Earth {
		private static Earth instance = null;
		private static Vector2 location;
	
		private Earth() {
			super();
			location = new Vector2(getX(), getY());
		}
	
		public static Earth getInstance() {
			if (instance == null) {
				instance = new Earth();
			}
	
			return instance;
		}
		
		[...]
	}

So when I’m creating an Earth in the main level class, I do something like this:

    public void create() {
		batch = new SpriteBatch();
		background = new Texture("background.png");
		earth = Earth.getInstance();
		alien = new Cucumberian();
    }

And do what I please with the instance.

Strategy

The Strategy Pattern (sometimes known by its street name - Policy Pattern) is all about figuring out how you want an algorithm to behave at runtime. This is the ad hocest (totally a word) implementation of a pattern in this post, but hopefully it’ll drive the point home.

I have a WeaponInterface. Here it is in all its completeness, thousands upon thousands of lines of code:

	public interface WeaponInterface {
		public float getWeaponDamage(float damage);
	}

I have two types of weapons that implement this interface - PowerfulWeapon and WeakWeapon. They represent the strategies, here’s how they both override the getWeaponDamage() method:

	public class WeakWeapon extends Weapon implements WeaponInterface {
		public WeakWeapon() {
			setDamage(1);
			setName("Super Weak Weapon");
		}

		@Override
		public float getWeaponDamage(float damageMultiplier) {
			return getDamage() * damageMultiplier;
		}
	}

	public class PowerfulWeapon extends Weapon implements WeaponInterface {
		public PowerfulWeapon() {
			setDamage(5);
			setName("Super Powerful Weapon");
		}

		@Override
		public float getWeaponDamage(float damageMultiplier) {
			return getDamage() * (damageMultiplier * 2);
		}
	}

You can see the difference in the way they calculate the damage.

So then when I’m creating a Murderdevastator or a Cucumberian I set an appropriate weapon ‘strategy’. In the current state of my code - the alien constructors decide which weapon strategy to use, but there is no reason why this can’t be up to the user, or completely randomised.

	public class Murderdevastator extends Alien {
		[...]

		public Murderdevastator(Vector2 position) {
			[...]
			setWeapon(new WeakWeapon());
		}
	}

	public class Cucumberian extends Alien {
		[...]
		
    public Cucumberian(Vector2 position) {
		[...]
		setWeapon(new PowerfulWeapon());
	}

You can happily see this working when you run the game and shoot the crap out of Earth, provided you’re collected enough to watch the health-bar.

Factory Method

The Factory Method Pattern is a pattern to create factory methods. Thank you, that is all for creation of objects without specifying a precise type of the object that will be created. To achieve that, we create a factory method that makes a promise to return an object. You can implement it in a base class and then override it in derived classes, or stick it in an interface and implement it in child classes, or do something else.

Say, Earth has a health bar that consists of smaller bars - red, orange and green. Since Earth’s health is pretty important - I’m using massive bars, so I have a LargeBar object. LargeBar extends Texture which is an in-built libGDX thing.

There are also alien spaceships. If in some future variation of the game the planet chooses to counter-attack - the aliens will also need health-bars, those will consist of much smaller bars. Happily breaking the YAGNI principle for the sake of making an ad hoc example, I have a SmallBar class, which also extends Texture.

Finally, I also have an abstract class - Damageable that implements three abstract methods for getting the right bars. Check out a few incomplete snippets:

	public abstract class Damageable {
		abstract protected Texture getRedHpBar();
		abstract protected Texture getOrangeHpBar();
		abstract protected Texture getGreenHpBar();
	}

Note that here the methods create a Texture object. And my Earth extends Damageable and its methods create LargeBar objects.

	public final class Earth extends Damageable {
		@Override
		protected Texture getRedHpBar() {
			return new LargeBar("earth/healthBarRed.png", barLocation);
		}

		@Override
		protected Texture getOrangeHpBar() {
			return new LargeBar("earth/healthBarOrange.png", barLocation);
		}

		@Override
		protected Texture getGreenHpBar() {
			return new LargeBar("earth/healthBarGreen.png", barLocation);
		}
	}

In an ideal world, a world where Earth can fight against alien invasions - there would be a point in adding health bars to alien ships. In my world Earth is a sissy, so alien ships don’t even bother to advertise their health.

And that covers the Singleton, Strategy and Factory Method patterns. Here’s a link to the full code again. Don’t be shy, feel free to share your opinions, critique or random words that came into your mind whilst reading this post - below.

Toodles.