State Design Pattern

Marcus Lee Eugene
4 min readOct 21, 2021

The State Design Pattern is a type of behavioural pattern and is used when there is a complex set of states to be handled with many different business rules to determine the transition of the state and how the new change in state should cause the program to behave.

I first learnt about this State Design Pattern during my internship at VRcollab where I worked on Game Development. I felt that it was a very systematic and clean way to transition between states of a program and it could also be extended to other areas of Software Engineering as well.

The Context

I was tasked to work on the Multi-Touch Interaction features in Unity for the company’s iPad mobile application. This required me to implement different touch gestures to perform the following actions:

  • Zoom into focus, Zoom out of focus (2-Finger Pinch)
  • Rotate Camera (2-Finger moving in different Angles)
  • Pan Camera (2-Finger Drag)

The actual work was done in C#, but for this article, I will be using Java to showcase the problem and solution.

The Problem

From the number of detected fingers on the screen and the change in distance and angle between the fingers, I was able to determine the desired behaviour. Initially, I lumped all my implementation of detecting fingers and performing actions into one function, here is an example:

Initial code

Looking good! However, a bug I faced from this implementation is that different gestures may collide with one another. For example, when the user is in the Zoom mode, it may fire the Rotate mode at the same time if the user moves his fingers in different angles while pinching by accident. This will cause the game camera to move around uncontrollably in random directions as it is constantly switching between zoom and rotate.

Temporary Fix

Okay… no problem, I can fix this! I shall add in Boolean flags: pinching, dragging and panning variables and use it to prevent the collision between all gestures.

However, notice that more Boolean flags needs to be created to prevent collisions between other gestures and the program will break each time we change something within the function. This becomes more complicated when gestures are added to the program with different scenarios, requiring many more boolean flags to be created and at some point it will be difficult to keep track of all of them.

The Solution

This is where the state pattern comes into play, reducing the complexity of handling state changes. We can refactor the code to be the following:

Gesture enum class

We create an enum class, with the different types of gesture states: PINCH, DRAG, ROTATE, RESET.

Function to determine touch gesture

We only require 1 Boolean Flag variable: stateLock which prevents all gestures from colliding with one another. When there are no fingers on the mobile screen, state = RESET and stateLock = false. When a gesture: Pinch, Drag, Rotate is detected, stateLock = true will prevent other gestures detected to interfere with this until the user removes the fingers from the screen to reset the state.

State handler

We will then have a gesture actions handler function which will read the current state and perform the actions required accordingly. With the new solution, it provides my program with stricter checks during transition between states, a more systematic approach in handling states and reduces the use of multiple Boolean Flags to “brute-force” the program to allow the scenario I want.

The determineGesture and handleGestureActions function are now flexible to account for different scenarios without breaking the program each time.

Pros & Cons

Pros:

  • Minimise conditional complexity
  • State robustness
  • Easy to convert a state plan from a finite state machine diagram into actual code

Cons:

  • Requires more code to be written depending on possible states
  • Each state requires one method to handle

Summary

The State Design Pattern simplifies the complexity of handling state changes, to allow new states to be added in without breaking previously implemented states. It has benefits such as minimising conditional complexity and allowing a programmer to quickly code up the logic with the aid of a finite state diagram. However more code may have to be written depending on the possible states.

I hope this article has been insightful!

References

Interested in learning more about me? Check out the following!

My Portfolio site: https://marcusleeeugene.github.io/

GitHub: https://github.com/marcusleeeugene

LinkedIn: https://www.linkedin.com/in/marcusleeeugene/

--

--