Design Patterns Guide
This article walks through every design pattern available in the WitDesignPattern package.
For the full source reference, browse the API documentation.
Singleton — MonoSingleton<T>
Guarantees a single instance of a MonoBehaviour exists across all scenes.
public class GameManager : MonoSingleton<GameManager>
{
public int Score { get; private set; }
}
// Access anywhere:
GameManager.Instance.Score++;
Observer — ObserverPattern<T>
Publish/subscribe without Unity events or C# delegates.
var onDied = new ObserverPattern<string>();
onDied.Subscribe(name => Debug.Log($"{name} died"));
onDied.NotifyObservers("Player");
Bindable — Bindable<T>
A reactive property that fires a UnityEvent when its value changes.
var health = new Bindable<int>(100);
health.OnValueChanged.AddListener(v => healthBar.fillAmount = v / 100f);
health.Value = 75; // UI updates automatically
State Machine — StateMachine + IState
Clean state management with enter/execute/exit lifecycle.
var sm = new StateMachine();
sm.ChangeState(new IdleState()); // calls Enter()
sm.Update(); // calls Execute() each frame
sm.ChangeState(new MoveState()); // calls Exit() then Enter()
Command — CommandInvoker + ICommand
Encapsulate actions with built-in undo support.
var invoker = new CommandInvoker();
invoker.ExecuteCommand(new PrintCommand("Fire!"));
invoker.UndoLastCommand();
Object Pool — ObjectPool<T>
Reuse objects instead of allocating/GC-ing them.
var pool = new ObjectPool<Bullet>(() => new Bullet(), initialCapacity: 20);
Bullet b = pool.Get();
// … use bullet …
pool.Release(b);
Factory — GenericFactory<TKey, TProduct>
Register and create products by key.
var factory = new GenericFactory<string, IWeapon>();
factory.Register("sword", () => new Sword());
factory.Register("bow", () => new Bow());
IWeapon w = factory.Create("sword");
Service Locator — ServiceLocator
A global, type-keyed registry for services.
ServiceLocator.Register<IAudioService>(new AudioService());
// … later …
var audio = ServiceLocator.Get<IAudioService>();
audio.Play("explosion");
Strategy — StrategyContext<TContext, TResult>
Swap algorithms at runtime.
var ctx = new StrategyContext<(int, int), int>(new AddStrategy());
ctx.ExecuteStrategy((3, 4)); // 7
ctx.SetStrategy(new MultiplyStrategy());
ctx.ExecuteStrategy((3, 4)); // 12
Builder — Builder<T>
Construct complex objects through a fluent API.
var player = new PlayerBuilder()
.SetName("Hero")
.SetHealth(100)
.SetSpeed(5.5f)
.Build();
Mediator — Mediator
Decouple systems by routing messages through a central hub.
var mediator = new Mediator();
mediator.Subscribe("OnScoreChanged", (sender, data) => Debug.Log(data));
mediator.Notify(this, "OnScoreChanged", 42);
Flyweight — FlyweightFactory<TKey, TFlyweight>
Share expensive data (meshes, textures) across thousands of instances.
var factory = new FlyweightFactory<string, TreeFlyweight>();
var oak = factory.GetFlyweight("oak", () => new TreeFlyweight { Mesh = "oak.fbx" });
oak.Operation(position);
Template Method — TemplateMethod<TInput, TResult>
Define an algorithm skeleton; let subclasses fill in the steps.
public class ParseInt : TemplateMethod<string, int>
{
protected override void PreProcess(string input) => Debug.Log("Validating…");
protected override int Process(string input) => int.Parse(input);
protected override void PostProcess(int result) => Debug.Log($"Got {result}");
}
ECS (Entity-Component-System)
Compose entities from pure-data components and drive behaviour from systems.
var entity = new Entity();
entity.AddComponent(new HealthComponent { Health = 100 });
new HealthSystem().Update(entity);
Prototype — IPrototype<T>
Clone configured instances rather than constructing from scratch.
public class EnemyConfig : IPrototype<EnemyConfig>
{
public int Hp; public float Speed;
public EnemyConfig Clone() => (EnemyConfig)MemberwiseClone();
}
Drag & Drop — DraggableItem<T> / DropZone<T>
Full Unity UI drag-and-drop with type-safe payloads, swap support, and visual feedback.
Formation Utils — FormationUtils
Generate world-space Pose lists for Circle, Line, V, Wedge, Box, Triangle, Echelon, Column, and Diamond formations.
List<Pose> poses = FormationUtils.GenerateCircleFormation(center, radius: 5f, count: 8);