← All patterns
Behavioral

Strategy

Swap out an algorithm at runtime by hiding each variant behind a common interface.

What Is It?

The Strategy pattern pulls a family of interchangeable algorithms out of the class that uses them. The user — the context — holds a reference to an interface like IAttackStrategy and calls Attack(target) without knowing whether a sword, a bow or a fireball is behind it.

Each concrete strategy (MeleeAttack, RangedAttack, MagicAttack) encapsulates its own range, damage and effects. Changing how the character fights means assigning a different object to one field, not editing an ever-growing if/else chain.

The strategies here are plain C# classes, but in production they are often ScriptableObjects: a designer creates a “Fire Staff” asset, tunes its numbers in the Inspector and drags it into the weapon slot. Picking up a new weapon at runtime simply swaps the reference.

When Is It Used?

Use it when one behaviour has several variants that you want to choose or change at runtime: weapons, AI targeting rules, movement modes, difficulty curves, pathfinding heuristics.

It is a good refactor whenever a method starts with switch (weaponType) and each branch is substantial. Each branch becomes a class with a single responsibility.

If there are only two tiny variants that never change at runtime, a simple parameter or a delegate (Func<float, float>) is lighter than a full interface and set of classes.

Interactive Demo

Click the controls and watch the objects collaborate. The console mirrors what the C# code below would log.

Code

Assets / Scripts / Behavioral/ Strategy ›StrategyTester.cs
using UnityEngine;

namespace Patterns.Behavioral.Strategy
{
    /// <summary>
    /// Client: picks strategies at runtime and tells the attacker to
    /// attack. Swapping weapons is just reassigning a reference.
    /// </summary>
    public class StrategyTester : MonoBehaviour
    {
        [SerializeField] private Attacker attacker;
        [SerializeField] private Transform dummy; // must have an IDamageable component
        [SerializeField] private Rigidbody arrowPrefab;

        private IAttackStrategy melee;
        private IAttackStrategy ranged;
        private IAttackStrategy magic;

        private void Awake()
        {
            melee = new MeleeAttack();
            ranged = new RangedAttack(arrowPrefab);
            magic = new MagicAttack();
            attacker.SetStrategy(melee);
        }

        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.Alpha1)) attacker.SetStrategy(melee);
            if (Input.GetKeyDown(KeyCode.Alpha2)) attacker.SetStrategy(ranged);
            if (Input.GetKeyDown(KeyCode.Alpha3)) attacker.SetStrategy(magic);

            if (Input.GetKeyDown(KeyCode.Space) && dummy.TryGetComponent(out IDamageable target))
                attacker.AttackTarget(target);
        }
    }
}
4 files · namespace Patterns.Behavioral.StrategyC# · UTF-8 · LF

Advantages & Disadvantages

+ Advantages

  • Algorithms are interchangeable at runtime without touching the context.
  • New variants are added as new classes, leaving existing, tested code alone.
  • Each strategy is small and isolated, which makes it easy to tune and unit test.

− Disadvantages

  • More types to manage; trivial variations may not justify their own class.
  • Callers must know enough about the strategies to choose the right one.
  • Strategies with very different data needs can force a bloated, lowest-common-denominator interface.

Tips

  1. 01Make strategies ScriptableObject assets so designers can create and balance variants without code changes.
  2. 02Keep strategies stateless where possible, so a single asset can be shared by many attackers.
  3. 03Pass a small context (attacker transform, target, stats) into the method instead of giving strategies references to everything.
  4. 04Strategy and State look alike in code. The difference is intent: a strategy is chosen from outside, while states trigger their own transitions.
  5. 05For one-off behaviours, a C# delegate or lambda is a perfectly valid lightweight strategy.