Wzorzec projektowy Komenda, ang. Command

Komenda jako polecenie do sterowania obiektem. Poszczególne zachowania dodawane są do listy komend invokera, z którego korzysta klient aby wywołać pożądane zachowania obiektu.
Wzorzec ten służy do enkapsulacji poleceń.

Komenda to wzorzec behawioralny, który umożliwia separację obiektu wykonującego operacje od obiektu, który je inicjuje. W tym artykule opisuję, jak można zaimplementować wzorzec Command w języku programowania Java.

Rys. 1. Schemat UML wzorca Command.

Wprowadzenie
Wzorzec Command pozwala na enkapsulację żądania jako obiektu, co umożliwia parametryzację klienta z różnymi żądaniami, kolejkowanie żądań, a także wspieranie operacji undo(). Składa się z kilku kluczowych elementów:

  • Command (Polecenie)
    Określa interfejs dla operacji.
public interface Command {

    void execute();

    void undo();
}
  • ConcreteCommand (Konkretne Polecenie)
    Implementuje interfejs Command i definiuje operację do wykonania.
public class PressMachineTurnOnCommand implements Command{

    private PressMachine pressMachine;

    public PressMachineTurnOnCommand(PressMachine pressMachine) {
        this.pressMachine = pressMachine;
    }

    @Override
    public void execute() {
        pressMachine.turnOn();
    }

    @Override
    public void undo() {
        pressMachine.turnOff();
    }
}
  • Invoker (Zamawiający)
    Wyznacza, kiedy i gdzie wykonuje się operacja.
public class WorkshopApp {

    private List<Command> commandQueue = new ArrayList<>();

    public void addToQueue(Command command) {
        commandQueue.add(command);
    }

    public void run() {

        if(commandQueue.isEmpty()) {
            System.out.println("Command list is empty.");
        }

        for(Command command : commandQueue) {
            command.execute();
        }

        commandQueue.clear();
    }

    public void undoLastCommand() {
        for(Command command : commandQueue) {
            command.undo();
        }
    }
}
  • Receiver (Odbiorca)
    Zna sposób wykonania operacji.
public class PressMachine {

    public void turnOn() {
        System.out.println("Press turned on.");
    }

    public void mountTool() {
        System.out.println("Tool mounted.");
    }

...
  • Client (Klient)
    Tworzy obiekt Command i przypisuje mu Receivera.
public static void main(String[] args) {

        PressMachine pressMachine = new PressMachine();
        WorkshopApp workshopApp = new WorkshopApp();

        workshopApp.addToQueue(new PressMachineTurnOnCommand(pressMachine));
        workshopApp.addToQueue(new PressMachineMountToolCommand(pressMachine));

...

        workshopApp.run();
        workshopApp.undoLastCommand();

    }

Szczegóły implementacji
W przykładowej implementacji interfejs Command definiuje metodę execute(). Klasa typu ConcreteCommand implementuje ten interfejs i przekazuje żądanie do obiektu Receiver. Obiekt Invoker decyduje, kiedy i jakie polecenie zostanie wykonane.
Klasy typu ConcreteCommand to klasy tworzone na podstawie dostępnych operacji do wykonania przez obiekt – receiver.
Obiekt Receiver w tym przykładzie to klasa PressMachine.
Obiekt Invoker w tym przykładzie to klasa WorkshopApp.

Podsumowanie
Wzorzec Command umożliwia elastyczne zarządzanie operacjami poprzez enkapsulację żądań. Dzięki temu możemy łatwo dodawać, usuwać lub modyfikować operacje bez konieczności zmiany kodu klienta. To podejście sprzyja również tworzeniu bardziej modularnego i rozszerzalnego oprogramowania. Wzorzec Command jest szczególnie użyteczny w sytuacjach, gdzie chcemy obsługiwać różne żądania, kolejkować je, czy też wspierać operacje undo, cofając wykonaną akcję wywołując metodę o przeciwnym działaniu.


Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *