Home Home
    Creational
  1. Singleton
  2. Factory
  3. Builder
  4. Prototype
    object composition and larger structures
  1. Decorator
  2. Flyweight
    Object communication
  1. Command
  2. Strategy

Software Design Patterns


It's harder to read code than to write it. - Joel Spolsky
// Single thread implementation
public class SimpleSingleton
{
    private static SimpleSingleton instance;
    //private constructor to not allow external initialization
    private SimpleSingleton() { }
    //static method to intialize class without creating class instance
    public static SimpleSingleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new SimpleSingleton();
            }
            return instance;
        }
    }
}

Singleton

one-instance, global-access, creation on demand, runtime-initialization, supports inheritance

if wrongly used as "helper" class = decrease-readability, promotes-coupling

concurrency-unfriendly, can not know when initialization will happen

Alternative = Pass instance, Store instance in base class, global class, Service Locator


// Flyweight interface
interface Shape {
    void draw(int x, int y);
}
// Concrete Flyweight
class Circle implements Shape {
    private String color; // *Intrinsic state*
    public Circle(String color) {
        this.color = color;
    }
    @Override
    public void draw(int x, int y) {
        System.out.println( color + 
        " x,y = " + x + "," + y;
    }
}

Flyweight

efficiently-reuse-objects , share large numbers of similar objects, save memory.

splits the state into intrinsic (shared) and extrinsic (unique) parts

Game Development, Networking Applications, Text Editors

Interface → Implementation stores intrinsic state ← Factory ← Client stores extrinsic state

Serialization

object to stream-of-bytes. Storable in memory, a database, or a file.


Empty ScriptableObject for Enum like comparison! Easier to extend.

[CreateAssetMenu(fileName='GameItem')]
public class GameItem : ScriptableObject
{ // Every GameItem can now be used as Enum GameItemType
    //Lets extend it with some business logic
    public GameItem weakness;
    public bool IsWinner(GameItem other)
    {
        return other.weakness == this;
    }
}

Scriptable Objects

Unity, data containers for shared data, static game configuration data, "read-only" persistent data.

First-class objects, reduce memory usage, assign to variable, pass as argument, method return, data type in data structures, serialiable, dynamic creation/destruction at runtime.

Can change values at runtime but maintains new values after execution termination.

Supports Unity events Awake, OnEnable, OnDestroy, OnDisable, OnValidate and Reset .

Inventories. Enemy, player, or item statistics. Audio collections

data containers = data that does not need to change at runtime

To avoid tampering = Encryption. Digital signatures (fingerprint algorithm to verify). Server-side validation (Authority rejects anything manipulated)

Finite State Machine

one state at any moment in time , finite number of states, decompose an object's behavior into 'chunks' or states.

    Two core operations
  1. ChangeState = can operate on input to make transitions from one state to another
  2. Execute = to cause an output or action to take place.
    state transition table = Conditions and the states those conditions lead to.
  • Embed the rules for the state transitions within the states themselves.
  • Provides an elegant way of implementing state-driven behavior.
  • Add enter and exit actions to each state; and call them via the agent's ChangeState method.


+-----------+   +--------------+   
|Interface  |-->|Magic Ability|   
+-----+-----+   +------+-------+   
      |                           
      |                                   
      |          +-----+------+        +-------------+
      +--------->+ Ability     +------>|Fire Damage |
                 | Decorator   |       |Decorator   |
                 +------------+        +-------+----+
                       |
                       |           +---------------+
                       +---------->|Heal Decorator |
                                   +-------+-------+


+-----------+     +----------------+   
|Controller  |--->|Ability Definition|   
+-----+-----+     +--------+-------+  
    |
    |          +--------------+   
    +--------->|Ability Factory|   
               +------+-------+  

Decorator

Wrapper pattern, Wrap around objects, add behaviour to **individual objects** without affecting the behaviour of other objects of same class.

Different characters - with same base spells - but merge with different spells.

Controller = Object creation using factory, Call Manager, Cast Spell

Manager = Singleton = Merge two abilities

Command Pattern

Action Pattern, method call &=rarr a stand-alone object.

Everything needed to execute that command is available to the class

Instead of directly calling a method to perform an action, you create a command object that holds all the information needed to execute that action.

Entity-Component System

ECS, Components are pure classes, almost entirely for data.

MVC

decouples views and models. multiple views to attach to a model.

Nestable, Utilizes Observer and Composite patterns

Controller class = implement response statergy = [Statergy Pattern](#statergy)

Factory Method = specify controller class

Decorator = add scrolling to view

Broker Chain Pattern

Broker Chain Pattern

// data class
class BaseStats { 
    int damage;
    int heal;
}
enum StatType {Damage, Heal}
class Stats {
    readonly BaseStats baseStats;
    int Damage { get {}} //modifier
    int Heal { get {} } //modifier
}
class StatsMediator {
    // Keep in memory because it is meant to access frequently
    readonly LinkedList<StatModifier> modifiers = new ();
    event EventHandler<Query> Queries;
    void PerformQuery(object sender, Query query) => Queries?.Invoke(sender, query);
    public void AddModifier(StatModifier modifier) {
        modifiers.AddLast(modifier);
    }
}
class Query {
    readonly StatType StatType;
    int Value;
    Query(StatType statType, int value) {
        StatType = statType;
        Valye = value;
    }
}
abstract class StatModifier {}