Head First Design Patterns

We can think design patterns as a set of best practices in Object-Oriented Design (OOD). It gives us a shared vocabulary, and simplifies communications with others by thinking at the pattern level instead of the nitty-gritty object level.

This book contains most of the design patterns defined in the textbook “Design Patterns: Elements of Reusable Object-Oriented Software”. For each pattern, I will summarize its design principles, definition, relation graph among example classes, with some code snippet.

Strategy Pattern

Definition: strategy pattern defines a family of algorithms/classes, encapsulates each one, and makes them inter-changeable. Strategy lets algorithms vary independently from clients that use it.

Design Principle:

  1. Encapsulate what varies: identify the aspects of your application that vary and separate them from what stays the same.
  2. Program to an interface, not an implementation.
  3. Favor composition over inheritance.

Composition means a HAS-A relationship, whereas inheritance means IS-A. Composition gives many benefits such as loosely-coupled class structures, dynamically changing behaviors at runtime, etc.

We use an example to demonstrate the disadvantages of not using the pattern and how strategy pattern resolves them by applying these design principles.

Suppose we are designing a Duck class hierarchy, in which each type of duck can fly and quack but their flying/quacking behaviors are not the same. First, let’s see two designs without strategy pattern:

  1. Use inheritance: first define an abstract Duck class with two abstract methods (fly, quack). Then for each actual Duck subclass, we inherit from Duck and implement the two methods.
  2. Use interface: first define an abstract Duck class and two interfaces (Flyable, Quackable). Then for each actual Duck subclass, we inherit from Duck and implement the two interfaces when necessary (e.g., one Duck can only fly).
Before Strategy Pattern
Class relationships without strategy pattern. Left is using inheritance; right is using interface.

Both of the two designs have disadvantages, for example:

  1. Classes are tightly-coupled: we cannot separate Ducks from behaviors. If we want to change a behavior implementation, we have to change all the client code (Ducks) that use this behavior (implementations). If $n$ Duck classes use the behavior, we have to change it in all $n$ classes.
  2. Low-level code reusing: if we want to create a DuckCall class hierarchy, we cannot reuse the quack behaviors defined in Ducks.
  3. Behaviors are binded to a class implementation and cannot be changed at runtime: after initializing a Duck object, we cannot change its behaviors.

Let’s see how strategy pattern can mitigate these issues. We know that what changes are behaviors not ducks. So we first separate the two behaviors from ducks by defining two interfaces, FlyBehavior and QuackBehavior, each of which has a set of classes implementing the behavior (Principle 1). Then, we add two objects of the interfaces to the (abstract) Duck class that hold the specific behavior implementations (Principle 2 and 3). Finally, for different types of Ducks (subclasses), we just need to pass the expected behavior implementations (Principle 3).

After Strategy Pattern
Class relationships in strategy pattern. We can see that client code (Duck) is separated from algorithms (here, behaviors) and use them via composition.

Now, let’s discuss how the design with strategy pattern resolves the disadvantages mentioned:

  1. We have a loosely-coupled class structures where client code (Duck) is separated from algorithms (FlyBehavior and QuackBehavior). If we want to change a behavior implementation, we don’t need to change client code.
  2. Since we already encapsulate behavior implementaions into separate interface/class structures that are not binded to client code, we can use them in other client code (e.g., DuckCall) via composition.
  3. We no longer bind behaviors to client code implementations. Instead, we use composition that holds behavior objects, so we can change the objects at runtime.

The key here is that, a duck now delegates its flying and quacking behaviors to coresponding behavior objects, instead of using quacking/flying methods defined in the Duck class (or subclass).

Observer Pattern

Keep objects notified when something they care happens. Publishers/Subject + Subscribers/Observers = Observer Pattern

Definition: observer pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

Design Principles:

  1. Strive for loosely coupled desings between objects that interact.

Observer pattern can be used in scenarios where a set of objects want to be automatically notified by a subject whenever it has updates. For example, weather displays want to be notified/updated whenever the weather station has new data. Or in GUI, action listeners want to be called whenever the button they listen to is triggered. In general, observer pattern has two parts:

  1. A subject class: the subject can add/remove observers and send updates to them. It also has a list (set also works) to save the set of subscribed observers.
  2. A Observer interface: an observer will hold a subject so that it can (un)subscribe the subject. It also has a single update (or other name) method that will be called by the subject whenever it has update.
  3. A set of classes that implement the Observer interface.
class WeatherStation {
private:
  std::vector<Observer *> observers;
  // And more data, e.g., temperature.
public:
  void registerObserver(Observer *);
  void removeObserver(Observer *);
  void notifyObservers();

  // And getters so that observers can pull data from subject.
}

class Observer {
private:
  WeatherStation *subject;
public:
  void update();  // Called by subject whenever it has update to send.
}
Observer pattern example
Class graph of the weather station example using observer pattern. The weather station is the subject and different displays are observers. Whenever the weather station has new data, it notify displays by calling their `update` method, which is the main component of `Observer` interface.

How Observer Pattern Achieves Loose Coupling:

  1. The only thing the subject knows about an observer is that it implements a certain interface (Observer interface).
  2. We can add or remove observers at any time.
  3. We don’t need to modify the subject to add new types of observers. We just create the new type which implements the Observer interface.
  4. We can reuse subjects and observers independently of each other.
  5. Changes to either the subject or an observer will not affect the other.

How to transfer the new data between subject and observers: subject can push data to observers via method arguments in Observer interface. Or observers can pull data from subject through its getter when there is update. Usually pull is more “correct” and extensible. If you use push, you may need to change the method API to include new arguments in the future.

Decorator Pattern

Definition: decorator pattern attaches additional responsibilities to an object dynamically and transparently. Decorators provide a flexible alternative to subclassing for extending functionality. Instead, decorators use subclassing only for type matching.

Design principles:

  1. Open-Closed: classes should be open for extension, but closed for modification.

Intuitively, we wrap the original object with one (or more) decorator(s), in a way such that the object can be used the same way (same APIs) as before, except that now it also have functionalities from these decorator(s). To make it work transparently:

  1. Decorators need to have the same APIs/interface as the object they decorate (inherit from the same interface or abstract class).
  2. Decorators need to HAS-A (wrap) an object, such that they can still access the object while adding new functionalities.
  3. We can implement decorator pattern by having a Decorator interface and a set of concrete Decorators classes that implement this interface and hold the decorating functionalities.

The below figure (from the book) shows the class structure of decorate pattern. Overall it consists of four types of elements:

  1. Component: the interface/abstract class that is implemented by both concrete components and decorators. Concrete components inherits it to implement expected behaviors, while decorators inherits it only for type matching.
  2. Concrete component: the set of objects/classes that can be decorated by decorators.
  3. Decorator: usually we also have an interface/abstract class so that we can have various concrete decorators that implement different decorations.
  4. Concrete decorators: various decorators that provide decoration implementations.
Decorator pattern class relationship
Classes and interfaces in decorator pattern.

Decorator pattern only works when you write code against the abstract component type, not the concrete component type. A concrete component will lose its own APIs (those not in the interface) after wrapped by a decorator. An example of decorator pattern is the Java.io package.

Let’s end up with a simple code snippet to demonstrate these elements:

// Base class. Every class/interface IS-A `Component`.
#include <string>

using std::string;

class Component {
public:
  virtual string description();
  virtual double price();
};

// Implement `Component` behaviors.
// Notice here, by using decorators, we will no longer have access to
// `ConcreteComponent`'s own behaviors, such as `discountPrice`.
class ConcreteComponent: public Component {
public:
  string description() override { return "coffee"; }
  double price() override { return 2.0; }
  double discountPrice(double percent) { return price() * percent; }
}

// Base decorator class. Decorator also IS-A Component, but only for type
// matching, not for extending behaviors. It HAS-A `ConcreteComponent` 
// (composition).
class Decorator: public Component {
public:
  Decorator(Component *comp) : component(comp) { }
protected:
  Component *component;
}

// Implement `Decorator`.
class ConcreteDecorator: public Decorator {
public:
  ConcreteDecorator(Component *comp): base(comp) { }
  string description() override { return "milk " + component->description(); }
  double price() override() { return 0.15 + component->price(); }
}

int main() {
  Component *coffee = new ConcreteComponent();
  Component *coffeeWithMilk = new ConcreteDecorator(coffee);
}

Factory Pattern

In Object-Oriented world, we usually have various classes that implement the same interface (e.g., different types of Pizza). This makes it difficult to creat object correctly and concisely, because we need to create a concrete object based on some inputs from user. And the same logic might be scattered across different locations in your codebase.

Imagine you need to “create” different Pizza objects based on a string input. And you need the Pizza creation logic both in createPizza and showPizzaMenu (or other) methods.

Factory pattern simplifies object creation by putting all object creation into a single place (either a factory method or a factory class). It has two main benefits:

  1. Decouple object creation from client code (code that uses the objects): client code no longer need to know how to create various objects. Whenever it needs an object (say, a Pizza), it can create the object by using the factory.
  2. Provide a consistent way of creating objects: only the factory knows and has the logic of object creation. Whenever we update the logic, we only need to change the factory.

Simple Factory

Simple factory is not a real design pattern, but it’s a widely-used type of factory. We simply put the object creation logic to a new Factory class, and whenever client code needs objects, it can use the Factory.

You can either create a factory object and pass it to client code, or write the object creation as a static method in the Factory and uses the static method directly in client code.

// Factory class. We only use the static method to create `Pizza`, so put 
// constructor in private.
class PizzaFactory {
public:
  static Pizza *createPizza(string pizzaType) {
    if (pizzaType == "cheese")
      return new CheesePizza();
    else if (pizzaType == "pepperoni")
      return new PepperoniPizza();
    else
      return UnknowPizza();
  }
private:
  PizzaFactory() = default;
}

// Client class. It uses factory to create pizza.
class PizzaStore {
public:
  Pizza *orderPizza(string pizzaType) {
    // Deligate pizza creation to the factory. 
    Pizza *pizza = PizzaFactory.createPizza(pizzaType);

    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();
    return pizza;
  }
}

However, simple factory does have some disadvantages, such as:

  1. Too flexible to be used correctly: in the above example, PizzaFactory and PizzaStore are two separate classes. After creating a Pizza, PizzaFactory no longer has control over the objects it creates. In fact, any code can use the factory to create pizza.
  2. Not extensible: if we want to have two factories that create NY-style pizzas and Chicago-style pizzas respectively, we need to have two separate Factorys.

Factory Method Pattern

Definition: factory method pattern defines an interface/method (a.k.a factory method) for creating objects, but lets subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclasses.

Design principle:

  1. Dependency inversion principle: depend upon abstractions. Do not depend upon concrete classes.

Now let’s see how factory method pattern resolve disadvantages in simple factory. First, it combines the two classes and moves the createPizza method to PizzaStore. Second, it defers object creation/instantiation to subclasses by declaring the createPizza as an abstract method. Then whenever there is a new style of pizza, we just need to inheriate the base PizzaStore and implement the createPizza method.

createPizza is the so-called factory method. A factory method handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from the object creation code in the subclass.

Factory Method Pattern
Factory Method Pattern
class PizzaStore {
public:
  Pizza *orderPizza(string pizzaType) {
    // Subclasses will handle object creation.
    Pizza *pizza = createPizza(pizzaType);

    pizza->prepare();
    pizza->bake();
    pizza->cut();
    pizza->box();
    return pizza;
  }
protected:
  abstract Pizza *createPizza(string pizzaType);
}

class NYStylePizzaStore: public PizzaStore {
protected:
  Pizza *createPizza(string pizzaType) override {
    if (pizzaType == "cheese")
      return new NYCheesePizza();
    else if (pizzaType == "pepperoni")
      return new NYPepperoniPizza();
    else
      return UnknowPizza();
  }
}

class ChicagoStylePizzaStore: public PizzaStore {
protected:
  Pizza *createPizza(string pizzaType) override {
    if (pizzaType == "cheese")
      return new ChicagoCheesePizza();
    else if (pizzaType == "pepperoni")
      return new ChicagoPepperoniPizza();
    else
      return UnknowPizza();
  }
}

As we can see, with factory method pattern, we can extend our PizzaStore to include different styles of pizza. Also only PizzaStore can create pizzas using the factory method (and the orderPizza method is also fixed, no other changes possible).

Abstract Factory Pattern

Definition: abstract factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Compared to factory method pattern which decouples object creation from client code by inheritance, abstract factory method uses composition to create different factories that follow the same Factory interface. Then with the same client code, we can create different types of objects by passing different factories.

Let’s assume that the key difference between different pizza styles is ingredients used. Then we can create an PizzaIngredientFactory interface, based on which we create two classes that implement the interface and provide ingredients for a specific pizza style. Every concrete Pizza class will hold a PizzaIngredientFactory reference and use it to produce different styles of pizza. When we implement concrete PizzaStores, we just need to pass the corresponding PizzaIngredientFactory (e.g., NYPizzaIngredientFactory) to the createPizza method.

By using abstract factory pattern, we also reduce the number of concrete Pizza classes needed. For example, we no longer need two cheese pizza classes (NYCheesePizza, ChicagoPepperoniPizza). Instead, we only need one CheesePizza and let the PizzaIngredientFactory passed to it decide the specific style.

Abstract Factory Pattern
Abstract Factory Pattern

Singleton Pattern

Sometimes we need one and only one instance of a class for some spefic tasks, such as resource management, thread pool, cache, etc. Having multiple instances will mess up the underlying resources.

Definition: singleton pattern ensures a class has only one instance, and provides a global point of access to it.

Below is a simple singleton pattern implementation in c++. Basically, we need 3 parts in a singleton pattern:

  1. Private constructor: ensure no external code can create an instance.
  2. Private static object: hold the only instance of the class.
  3. Public static getInstance method: create the only instance if yet created and return the reference of the singleton.
class Singleton {
public:
  static Singleton const *getInstance() {
    if (uniqueInstance == nullptr) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }

  // other methods here.
private:
  static Singleton const *uniqueInstance;
  
  Singleton() {}
};

Although being a simple pattern, singleton pattern can be tricky when used with other programming tools such as inheritance, serialization/deserialization, reflection, etc. For example, in multithreading setting, the above code will accidently create more than one instance if getInstance is called simutaneously by multiple callers. There are several fixes for this issue:

  1. Make the getInstance method a syncronization method. Easy but add high overhead.
  2. Eagerly create the instance instead of lazy creation. No sync/lock needed, but one instance is created no matter if it’s used.
  3. Reduce the use of syncronization by only locking the object creation part. E.g., if the object is created, return it directly. Add low overhead but hard to implement correctly.

Singleton v.s. Enum

In some languages like Java, singleton pattern can be easily implemented as an Enum. Conceptually they are similar as both have only one instance.

public enum Singleton {
  UNIQUE_INSTANCE;
  // more field here.
}

public class SingletonClient {
  public static void main(String[] args) {
    Singleton singleton = Singleton.UNIQUE_INSTANCE;
    // use singleton here.
  }
}

Command Pattern

Suppose we have many different devices, all of which can be turned on/off but the exact actions to do it are different. We want to design a unified remote control that is able to turn on/off these devices by pressing corresponding buttons. If we embed a device’s actions for that request to a specific button, there will be at least two disadvantages:

  1. RemoteControl class and Device are tightly coupled. To modify a button’s request, we have to change RemoteControl’s code.
  2. We cannot dynamically change a button to handle another type of request.

Not to mention that such a design violated many OO principles, such as: programming to interface, not implementation, loosely couple, etc.

Command pattern can be used to overcome these disadvantages given such a requirement.

Definition: command pattern encapsulates a request as an object (Command), thereby letting you parameterize other objects (Receiver) with different requests, queue or log requests, and support undoable operations.

The command object is like a surrogate between invokers (that send requests) and receivers (that need to do the actions).

Usually a command pattern implementation includes the following components: client, invoker, command, receiver. Let’s go throught them from easy to hard.

Receivers are just some concrete classes that can make actions based on request, such as Light (On/Off), GrageDoor (Open/Close), etc.

Command is the key to decouple invokers and receivers. It’s an interface based on which various concrete command implementations encapsulate different receivers and use them to complete requests (via the interface method execute).

class Command {
public:
  virtual void execute();
};

// here the `light` is the receiver, and `on()` is the action.
class LightOnCommand: public Command {
public:
  LightOnCommand(Light *light) {
    this.light = light;
  }

  void execute() {
    light->on();
  }
private:
  Light *light;
}

Now that we have a receiver and command, how can we load and use them. Invoker comes to help by holding a command and ask the command to execute a request at some point. So an invoker has two functionalities: set a command and ask it to execute. For example, we may have a remote control invoker that is responsible for turning on a light (let’s also assume we can dynamically change the Command it holds):

class RemoteControl {
public:
  void setCommand(Command *command) {
    this.command = command;
  }

  void pressButton() {
    command->execute();
  }

private:
  Command *command;
};

int main() {
  RemoteControl invoker;

  // Command
  Command *lightOn = new LightOnCommand(new Light());
  Command *grageOn = new GrageOnCommand(new Grage());

  // Notice the invoker is decoupled from actual receivers,
  // and can complete different requests using the same interface.
  invoker.setCommand(lightOn);
  invoker.pressButton();

  invoker.setCommand(grageOn);
  invoker.pressButton();
}

Notice in the above code, we simply create two commands and load them to the invoker in the main function. In real world, there might be a lot of commands and we need to load them all to their invokers. That’s done by a specific class called Client. For example, a real RemoteControl might have 7 command slots for turning on receivers and another 7 for turning off receivers. Then a client will be responsible for creating these receivers, binding them to corresponding OnCommand/OffCommand, and returning the complete RemoteControl for real usage.

Command Pattern
Class diagram of command pattern. A receiver object is encapsulated into a command object. The command object lets the receiver object make actions to complete a request via its `execute` interface method. Then whenever a request comes, the invoker can always call a command's `execute`. The underlying receiver is isolated from invokers. Client is mainly used to create and assemble all other classes (e.g. create command, receiver, etc).

Additional functionality

Lambda expression

In some languages such as Java, we can use lambda expressions in replace of command classes, which can significantly simplify the code. Notice this only works if the Command interface has one abstract method.

Add more methods to Command

Say we want the RemoteControl to be able to undo its last command. We need to make two changes. First, for each Command, we need to define how to undo the Command by adding a undo method in the Command interface. Then the RemoteControl also need to the last Command object it invokes.

class Command {
public:
  virtual void execute();
  virtual void undo();
};

class LightOnCommand {
public:
  // ... same code.

  void undo() {
    this.light->off();
  }

private:
  // ... same code.
};

class RemoteControl {
public:
  // Add a new `undo` button (invoker)
  void pressButton() {
    // Now we need to update the `lastCommand` invoked.
  }
  void pressUndoButton() {
    this.lastCommand->undo();
  }
}

private:
  // ...same code.
  Command *lastCommand;

  #### MacroCommand

Sometimes we want to have a "smart" command that is able to complete multiple commands at once, in which we can use `MacroCommand` A `MacroCommand` object holds a `Command` array and, when called, executes all `Commands` one by one.

```cpp
class MacroCommand: public Command {
public:
  MacroCommand(Command[] commands) {
    this.commands = commands;
    this.length = sizeof(commands)/sizeof(commands[0]);
  }
  void execute() {
    for (int i = 0; i < this.length; i++) {
      this.commands[i].execute();
    }
  }

  void undo() {
    for (int i = this.length - 1; i >= 0; i--) {
      this.commands[i].undo();
    }
  }
}

Using command pattern for logging requests

In some applications, especially distributed applications, the system need to log all the requests it handles. In crash happens, the system re-executes all requests since last checkpoint to recover its state.

Using command pattern, we can add two methods, store() and load() to the Command interface. Whenever an execute happens, we store the Command on disk by seralizing the object. After the system recovers from crash, we load all stored commands and execute them in batch.

Notice in some languages we need to handle some seralization/deseralization caveats.

Adapter and Facade Patterns

We know that the decorator pattern is used to add new functionality while keeping an interface unchanged. It accomplishes this by wrapping an interface object and implementing the same interface.

Adapter and facade patterns are two patterns that also wraps interfaces/classes, but for different purposes: one is to changing an interface (or interfaces) to another, and the other is to simplify an interface (or interfaces).

Adapter pattern

Definition: adapter pattern converts the interface of a class into another that the clients expect, making classes with incompitable interfaces able to work together.

For example, a client expects a class implementing interface A (target), while we have a class implementing interface B (adaptee). We can define a class Adapter that holds a reference to B and implements A by using the B object. By using Adapter, all classes that implements B can be used in places where A is expected.

class Walker {
public:
  abstract void walk();
};

class Runner {
public:
  abstract void run();
};

class WalkerAdapter: public Runner {
public:
  WalkerAdapter(Walker *w): walker(w) { }

  void run() {
    for (int i = 0; i < 5; i++) {
      walker->walk();
    }
  }
private:
  Walker *walker;
};

int main() {
  Walker *walker = new ConcreteWalker();
  Runner *runner = new WalkerAdapter(walker);

  // Now we can use the runner as usual. Under the hook,
  //  it's the adaptee, walker, who is running.
  runner.run();
}

Facade pattern

Definition: facade pattern provides a unified interface to a set of interfaces in a subsystem. It makes the subsystem easier to use by providing a higher-level interface. (e.g., imagine it as a wrapper class of a set of objects.)

Suppose we have a complex home theather system which consists of many devices such as projectors, screens, amplifiers, etc. The client (e.g., a controller) need to open them all when watching a movie and close all after watching. Moreover, if we want to upgrade the system, we have to change the client code to use the upgraded devices.

Instead, we can have a Facade class (better let the vendor supply it) that holds the complex system and defines some common methods, such as watchMoive, endMoive, etc. With the Facade, we no longer need to care how the system operates under the hook. Even when we want to upgrade the system, we don’t need to change our client code, but only need a new Facade. Below is a class diagram with a Facade on top of a theather system:

Facade pattern
A facade class is used to simplify the home theater system. With facade, the client no longer need to know details about the underlying system, but only need to know the simple interface in the facade.

Principle:

Least knowledge (a.k.a., law of demeter): talk only to your immediate friends. Reduce the interactions between objects to just a few close “friends”.

What the principle suggests is that, we need to find the correct abstractions when we have many different objects in our system. If we simply use all directly, they will be tightly coupled and hard to extend. Instead, we should put objects that are more related into a Facade with simplified methods and let others use the Facade.

Template Method Pattern

TODO

Template method pattern defines an algorithm in a method (template method) which consists of multiple steps (other methods). These steps can be abstract methods and implmentations can be left to concrete sub-classes.

Iterator Pattern and Composite Pattern

TODO

Iterator pattern provides a unified way of iterating a collection of elements, by using hasNext() and next() methods. Often we can implement a Iteratable interface that returns an iterator object, so that we no longer need to care which types of Iterator we are using.

Composite pattern is good at representing a tree structure, by using a Component interface. A Component can be either an Item (a leaf that has no child), or a Composite that consists of a set of other Component (where recursion happens).

State Pattern

Definition: the state pattern allows an object (Context) to alter its behavior when its internal state (State) changes. The object will appear to change its class.

State pattern
The state pattern consists two parts: one is Context which is the main point interacting with users and changing its behaviors based on its State, and State which controls the concrete behaviors given an action.

State pattern fits the senario where you have a set of actions and states. Each action has different behaviors at a given state. And a state will transit to another state when an action happens. For example, a simple vending machine might have two states (in-stock and out-of-stock) and two actions (purchase, replenish). Given the in-stock state, purchase will decrease the machine’s stock count while replenish will increase. If after any action the stock count becomes 0, the state is transitted to out-of-stock.

A simple but non-extensible implementation can be that we use enums to represent states and implment each action as a function which has different behaviors conditioned on states. However, such a design is not well-encapsulated. If we want to add a new state, we need to update all functions to include it. The same applies if we want to change the behaviors given a state.

By using the state pattern, we decouple different states and encapsulate them into individual classes. All concrete states implement the same State interface, which defines all supported action methods. Each concrete state is responsible for implementing the action behaviors.

There is also a Context class (e.g., the vending machine) that interacts with users and holds an State object (and metadata, such as stock count, etc). Context delegates the actions from users to the State it holds, and possibly change the State to another one.

Some implmentation considerations:

  1. A Context object usually holds and initializes all State objects at once such that later on it doesn’t need to create State objects whenver state transition happens.
  2. State transition can be controlled either by Context or by State.
    1. If by State, we can let each State holds a reference back to Context and updates its state to the new one.
    2. If by Context, usually we need to a fixed state trainsition.
  3. The State interface can be implemented as an abstract class if we want to provide some default implementations.
updated_at 21-11-2021