Command Pattern – acțiuni tratate ca obiecte independente

  • Doru Bulubasa
  • 15 December 2025

În aplicațiile reale, acțiunile utilizatorilor sau ale sistemului pot deveni rapid complexe: salvare, anulare, refacere, programare de task-uri, macro-uri sau cozi de procesare. Dacă aceste acțiuni sunt implementate direct în UI sau în clasele care le declanșează, aplicația devine greu de extins și de întreținut.

Command Pattern rezolvă această problemă prin transformarea fiecărei acțiuni într-un obiect independent, care conține toate informațiile necesare pentru a fi executat. Astfel, cererea este complet decuplată de obiectul care o execută.


Ce problemă rezolvă Command Pattern?

Fără Command Pattern:

  • UI-ul cunoaște logica de business

  • acțiunile nu pot fi ușor refăcute (undo/redo)

  • este dificil să adaugi acțiuni noi fără a modifica cod existent

Cu Command Pattern:

  • acțiunile sunt obiecte de sine stătătoare

  • poți stoca, jurnaliza sau reexecuta comenzile

  • poți construi mecanisme de undo/redo sau macro-uri


Structura Command Pattern

Pattern-ul este format din patru componente principale:

  1. Command – interfață sau clasă abstractă care definește metoda Execute()

  2. ConcreteCommand – implementează comanda concretă

  3. Receiver – obiectul care execută efectiv acțiunea

  4. Invoker – obiectul care declanșează comanda

Opțional:

  • Undo() – pentru inversarea acțiunii

  • Command History – pentru stocarea comenzilor executate


Diagramă conceptuală (descriere)

Invoker → Command → Receiver

Invoker-ul nu știe ce face comanda, doar o execută.


Exemplu simplu în C#

1. Interfața Command

public interface ICommand
{
    void Execute();
}

2. Receiver – logica de business

public class Light
{
    public void TurnOn()
    {
        Console.WriteLine("Lumina a fost aprinsă");
    }

    public void TurnOff()
    {
        Console.WriteLine("Lumina a fost stinsă");
    }
}

3. Concrete Commands

public class TurnOnLightCommand : ICommand
{
    private readonly Light _light;

    public TurnOnLightCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOn();
    }
}
public class TurnOffLightCommand : ICommand
{
    private readonly Light _light;

    public TurnOffLightCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOff();
    }
}

4. Invoker

public class RemoteControl
{
    private ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void PressButton()
    {
        _command.Execute();
    }
}

5. Utilizare

var light = new Light();

var turnOn = new TurnOnLightCommand(light);
var turnOff = new TurnOffLightCommand(light);

var remote = new RemoteControl();

remote.SetCommand(turnOn);
remote.PressButton();

remote.SetCommand(turnOff);
remote.PressButton();

Implementarea Undo / Redo

Command Pattern devine extrem de puternic atunci când adăugăm suport pentru anulare.

Extinderea interfeței

public interface ICommand
{
    void Execute();
    void Undo();
}

Command cu Undo

public class TurnOnLightCommand : ICommand
{
    private readonly Light _light;

    public TurnOnLightCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOn();
    }

    public void Undo()
    {
        _light.TurnOff();
    }
}

Istoric comenzi

public class CommandManager
{
    private readonly Stack<ICommand> _history = new();

    public void ExecuteCommand(ICommand command)
    {
        command.Execute();
        _history.Push(command);
    }

    public void Undo()
    {
        if (_history.Any())
        {
            var command = _history.Pop();
            command.Undo();
        }
    }
}

Exemple reale unde se folosește Command Pattern

  • Undo / Redo în editoare (Word, Photoshop)

  • Sisteme de meniuri și butoane

  • Task queues și job scheduling

  • Macro-uri (execuție în lanț de comenzi)

  • CQRS (Command side)


Avantaje

✔️ Decuplare completă între UI și business logic

✔️ Extensibilitate fără modificarea codului existent

✔️ Suport nativ pentru undo/redo

✔️ Testare ușoară a comenzilor individuale


Dezavantaje

❌ Crește numărul de clase

❌ Poate fi overkill pentru aplicații simple


Command Pattern vs Strategy Pattern

Command

Strategy

Reprezintă o acțiune

Reprezintă un algoritm

Poate fi stocată

De obicei nu

Suportă undo/redo

Nu

Executare punctuală

Comportament pe termen lung

 


Concluzie

Command Pattern este un pattern esențial pentru aplicații moderne și extensibile. Atunci când acțiunile devin obiecte independente, aplicația câștigă flexibilitate, testabilitate și control.

Dacă ai nevoie de undo/redo, cozi de procesare sau macro-uri, Command Pattern este alegerea potrivită.

Scrie un comentariu

Adresa de mail nu va fi publicata. Campurile obligatorii sunt marcate cu *