Home Home

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

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 {}