<aside> 💡
Een Factory verstopt het aanmaken van objecten achter één methode, zodat de aanroepende code niet zelf hoeft te weten welke concrete klasse er precies gebouwd wordt.
</aside>
Stel je bouwt in TrainForge een trainingsmodule waarin een cursist verschillende procedures kan oefenen, een KlimProcedure (veilig een frame beklimmen) of een AlarmProcedure (correct reageren op een noodsituatie), en er komen ongetwijfeld nog meer procedures bij. Als je overal in je code letterlijk new KlimProcedure() of new AlarmProcedure() schrijft zodra een cursist een oefening start, moet je bij elke nieuwe procedure door je hele codebase heen om al die plekken aan te passen. De code die een procedure start raakt onnodig gekoppeld aan elk concreet procedure-type dat bestaat.
Je zet het aanmaken op één plek: een factory-klasse met een methode die op basis van een parameter (bijvoorbeeld een enum ProcedureType) het juiste concrete object teruggeeft, maar altijd getypeerd als de gedeelde basisklasse. De rest van je code werkt alleen nog met die basisklasse, en weet niet (en hoeft niet te weten) welk concreet procedure-type er precies achter zit.

In het diagram zie je:
public enum ProcedureType { Klim, Alarm }
public class ProcedureFactory
{
public Procedure Maak(ProcedureType type)
{
switch (type)
{
case ProcedureType.Klim: return new KlimProcedure();
case ProcedureType.Alarm: return new AlarmProcedure();
default: throw new ArgumentException("Onbekend procedure-type");
}
}
}
Gebruik vanuit een andere klasse:
Procedure procedure = procedureFactory.Maak(ProcedureType.Klim);
trainingManager.StartSessie(procedure);
trainingManager.StartSessie() hoeft nergens KlimProcedure of AlarmProcedure te kennen — alleen Procedure.
In een VR-project bestaat een procedure meestal niet als los C#-object, maar als een prefab met scripts, gekoppelde 3D-modellen en triggers erin. De factory geeft dan niet zomaar een new-object terug, maar instantieert het juiste prefab en geeft de bijbehorende component terug:
public abstract class Procedure : MonoBehaviour
{
// let op: bewust niet 'Start()' genoemd — dat is al een Unity-lifecycle method
public abstract void StartProcedure();
}
public class KlimProcedure : Procedure
{
public override void StartProcedure() { /* animaties, audio, trigger-zones activeren */ }
}
public class AlarmProcedure : Procedure
{
public override void StartProcedure() { /* sirene, noodverlichting, spawn-punten activeren */ }
}
public class ProcedureFactory : MonoBehaviour
{
[SerializeField] private KlimProcedure klimProcedurePrefab;
[SerializeField] private AlarmProcedure alarmProcedurePrefab;
public Procedure Maak(ProcedureType type)
{
Procedure prefab = type switch
{
ProcedureType.Klim => klimProcedurePrefab,
ProcedureType.Alarm => alarmProcedurePrefab,
_ => throw new ArgumentException("Onbekend procedure-type")
};
return Instantiate(prefab, transform.position, Quaternion.identity);
}
}
Procedure procedure = procedureFactory.Maak(ProcedureType.Klim);
procedure.StartProcedure();
De prefab-referenties (klimProcedurePrefab, alarmProcedurePrefab) sleep je in de Inspector op de ProcedureFactory, zo blijft het aanmaken data-gedreven in plaats van hardcoded, en kan een level-designer zonder code aan te raken een nieuw prefab koppelen.