Welcome to part 1 of the Design Patterns series!
This episode will be about the Façade Pattern!
Façade Pattern
Façade Pattern is a very basic pattern we often unknowingly use. It’s a very useful pattern which is used in lots of applications.
Just as many patterns, the name says a lot about what the pattern does. As Façade means: “the principal front of a building, that faces on to a street or open space”.
In coding terms you can see this as a central access point. It’s the façade of a feature or your game which has access to multiple classes to call actions.
Examples
You can also compare it to a hub. You can setup an AI hub in your home controlling your media players, kitchen and cleaning devices. Your smart home device will be the façade of all these actions. You’ll ask the smart home device (façade) to start the music and start cleaning.
Another example you can think of is an ATM! When you want to get money out of an ATM a lot of things will happen in the background. It’ll check your pin-code registered to your bank account. It will check if the amount of money you want to subtract is possible and in the end it will provide you the money if all conditions are correct or show an error why it couldn’t happen.
The user doesn’t know about the actions an ATM is doing. All it asks is money, and asks the ATM to deliver it when the user has the right conditions.
Intentions of using Façade pattern
- Improving readability by having a central point of handling actions in order or sequences.
- Easy access/launching point.
Demo
Demo introduction
For this demo I decided to make a simple guess game. The goal is to keep the sorcerer alive by giving it the right type of food. When you give it the wrong type of food, it will be so disappointed resulting in killing himself. That’s not what we want! 😜
As I explained in examples section, a façade is the central point of delegating action. Such as an ATM. In this demo there’s one façade to control the game.
When you press any button, the game will trigger the sorcerer to eat. If the sorcerer dies, the façade will enable a restart button and allow you to try again. If the sorcerer survives, the sorcerer will recall a type of food. Every time the sorcerer is eating the façade will disable all food buttons so the user is forced to wait.
In steps:
- Facade got access to the sorcerer, all food buttons and a reset button.
- When the sorcerer calls out to eat food, all food buttons will enable.
- When the user presses any of the food buttons, all buttons will be disabled, the sorcerer will eat it and decide to die or not.
- When sorcerer dies.
- All food buttons remain inactive.
- Reset button will be enabled, if pressed the whole procedure will restart
- When sorcerer survives
- Sorcerer will call out for food again, all food buttons will enable.
Setup
For this demo I am using Unity 2019.4.10f, but you can follow this series with any version you like!
For some visual effects I installed DoTween to code some small tween animations you will see later in code examples. Also do I use DoTween to make delayed calls.
The hierarchy:
Hierarchy is based of a few simple objects.
- background, first layer for scenery
- sorcerer, character who eats food
- front background to add some depth. Makes the sorcerer stand behind the bushes
- food buttons container
- All food type buttons
- Made a master button so it was easy to change/modify original design without having to change each individual button
- button reset to reset our game
- façade
Sorcerer character contains an animator with three animations:
idle -> eat is linked to Eat trigger.
eat -> idle has an end time to transition back to idle.
idle -> die is linked to Die trigger.
die -> idle is linked to idle in case we want to reset.
Code
Actions
Sorcerer.cs
Sorcerer will be our character who eats food and visualise the message to the user.
Therefor it has two public accessible method for eating and setting it’s target.
namespace Facade.Code { // to make sure we have an animator on this instance we add a require component attribute. [RequireComponent(typeof(Animator))] public class Sorcerer : MonoBehaviour { // to visualise which type of food we want to eat [SerializeField] private Text _targetLabel; // to trigger animations private Animator _anim; private int _currentTarget; // Two event actions we will listen to in Facade public event Action OnDied; public event Action OnSurvived; private void Start() { // get animator _anim = GetComponent<Animator>(); // set target label alpha to 0 _targetLabel.DOFade(0, 0); } // Set food type target public void SetTarget(int target, string foodString, Action onSetLabel) { _currentTarget = target; _targetLabel.text = $"Give me: {foodString}"; // Fade in the text label asking the food type _targetLabel.DOFade(1, 0.2f).SetDelay(2).OnComplete(() => { // Fade out the text label so the user can't peak anymore what the sorcerer wants to eat. _targetLabel.DOFade(0, 0.1f).SetDelay(0.5f); // Call action to tell facade the question is visible! onSetLabel?.Invoke(); }); } // Start eating progress and check whether we died or not public void Eat(int target) { _anim.SetTrigger("Eat"); if (_currentTarget != target) { // Die after 3 seconds to make it exciting if the user choose right or wrong. DOVirtual.DelayedCall(3f, Die); } else { // Call survive event after 1.5 seconds to start whole process over. DOVirtual.DelayedCall(1.5f, () => OnSurvived?.Invoke()); } } private void Die() { _anim.SetTrigger("Die"); // call die event OnDied?.Invoke(); } } }
FoodMenu.cs
To control all buttons enabling/disabling, we add a food menu class which accesses all buttons.
namespace Facade.Code { public class FoodMenu : MonoBehaviour { // all buttons set in inspector [SerializeField] private Button[] _buttons; // set all buttons intractability to false public void DisableButtons() { for (int i = 0; i < _buttons.Length; i++) { _buttons[i].interactable = false; } } // set all buttons intractability to true public void EnableButtons() { for (int i = 0; i < _buttons.Length; i++) { _buttons[i].interactable = true; } } } }
FoodType.cs
Food type is a short data struct so we can set the food type’s name and icon.
namespace Facade.Code { // making this struct serializable so it's visible in the editor inspector [System.Serializable] public struct FoodType { public string Name; public Sprite Icon; } }
Facade
GameFacade.cs
Now we have all actions set up as puzzle pieces, we can setup our facade!
namespace Facade.Code { public class GameFacade : MonoBehaviour { // access points [SerializeField] private FoodType[] Targets; [SerializeField] private Sorcerer sorcerer; [SerializeField] private FoodMenu _foodMenu; [SerializeField] private Button _reset; [SerializeField] private Image _foodIcon; // current target private int _target = -1; private void Start() { // initializing objects _reset.onClick.AddListener(Reset); _reset.gameObject.SetActive(false); // listening to sorcerer events sorcerer.OnSurvived += RandomTarget; sorcerer.OnDied += OnEnemyDied; // disabling all buttons on start _foodMenu.DisableButtons(); // set a random target RandomTarget(); } private void RandomTarget() { // get a random target number _target = Random.Range(0, Targets.Length); // set sorcerer target to start label animation // enable all buttons once target is set. sorcerer.SetTarget(_target, Targets[_target].Name, _foodMenu.EnableButtons); } // Called by button onclick events in editor. public void Eat(int target) { // disable all buttons _foodMenu.DisableButtons(); // set food icon sprite, which will be animated by sorcerer .Eat method _foodIcon.sprite = Targets[target].Icon; // start eat animation sorcerer.Eat(target); } private void OnEnemyDied() { // enable reset button when enemy died _reset.gameObject.SetActive(true); } private void Reset() { sorcerer.OnSurvived -= RandomTarget; sorcerer.OnDied -= OnEnemyDied; // reset current scene SceneManager.LoadScene(SceneManager.GetActiveScene().name); } } }
Inspector:
As you can see in this example, we can access, change and modify everything through our game façade. We can add new targets, link access points and so change these too.
The user can only interact through the food buttons. So the food buttons call the game façade .Eat method passing their target number.
Git
Find the repository here with full source code:
https://github.com/jscotty/DesignPatterns
Or download the unity package here:
Break down
I made this simplified UML diagram to break down what happens.
As you can see, the user only talks with the Façade by pressing the buttons. This makes the user not having to care what the rest does. All it wants to do is to provide the target index he/she thinks the sorcerer wants to survive. The façade delegates this through the actions.
This makes this example comparable to an ATM I explained in the beginning. All the user does is pressing buttons and the façade will delegate it further to receive returns.
Most important to do when developing Façades in your project, is to think in access points. When “I” as a “user” want to get … , who/what do I contact/interact with to receive my return. The user does not know what happens in background, but the contact/interaction access point knows what sequence has to happen. 😉
Resources
Derek Banas
A great simple explanation of façade pattern bank demo.
Simply Explained
Perfect simple example of a home theatre façade explained in TypeScript.
Wikipedia
This Wikipedia page is a great in-depth explanation of possibilities with Facade Pattern.
https://en.wikipedia.org/wiki/Facade_pattern
Assets
For the demo below I used three free art packages!
– Evil Wizard
– Free Pixel Art Hill
– Free Pixel Foods
Hope you enjoyed this episode!
Did you already know about Façade pattern? Or did you just realize you’ve been using it unknowingly all the time! (I did so once I learned about it 😜 )
If any questions, feel free to message me on Instagram @justinbieshaar or in comments below!
Happy coding everyone! 👨💻
Greetings,
Justin Scott
Leave a Reply