Menu
Coddy logo textTech

Wzorzec polecenia

Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 70 z 87.

Wzorzec Polecenia to behawioralny wzorzec projektowy, który przekształca żądanie w samodzielny obiekt zawierający wszystkie informacje o tym żądaniu. Dzięki tej transformacji możesz przekazywać żądania jako argumenty metod, opóźniać ich wykonanie lub umieszczać je w kolejce, a także obsługiwać operacje, które można cofnąć.

Pomyśl o tym jak o restauracji: zamiast mówić kucharzowi bezpośrednio, co ma ugotować, zapisujesz zamówienie na kartce. Kelner (wywołujący) zanosi kartkę (polecenie) do kuchni, gdzie można ją umieścić w kolejce, nadać jej priorytet, a nawet anulować. Ten wzorzec oddziela obiekt wywołujący operację od obiektu, który ją wykonuje.

Wzorzec ma cztery kluczowe elementy: interfejs Command deklarujący metodę execute, klasy ConcreteCommand implementujące konkretne działania, obiekt Receiver wykonujący właściwą pracę oraz obiekt Invoker wywołujący polecenia:

interface Command {
    void execute();
}
class Light {  // Odbiornik
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}
class RemoteControl {  // Wywołujący
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Wywołujący nie wie, jakie działanie zostanie wykonane. Po prostu wywołuje execute():

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Wynik: Light is ON

Wzorzec polecenia sprawdza się doskonale, gdy trzeba kolejkować operacje, zaimplementować funkcję cofania i ponawiania lub zaplanować zadania do późniejszego wykonania. Każde polecenie zawiera wszystko, co jest potrzebne do wykonania działania, dzięki czemu system staje się bardziej elastyczny i rozszerzalny.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system automatyki inteligentnego domu z użyciem wzorca polecenia! Stworzysz system, w którym różnymi urządzeniami domowymi można sterować za pomocą poleceń, co pozwala kolejkować i wykonywać działania, a nawet przechowywać je do późniejszego użycia — podobnie jak w przypadku uniwersalnego pilota, który nie musi wiedzieć, jak działa każde urządzenie.

Rozmieścisz kod w czterech plikach:

  • Command.java: Zdefiniuj interfejs Command, który będą implementować wszystkie polecenia urządzeń. Powinien deklarować jedną metodę execute(), która wykonuje działanie polecenia.
  • Devices.java: Utwórz dwie klasy odbiorników, które reprezentują urządzenia inteligentnego domu:

    Television — ma metody powerOn(), która wypisuje TV is now ON, powerOff(), która wypisuje TV is now OFF, oraz setChannel(int channel), która wypisuje TV channel set to [channel].

    Thermostat — ma metody setTemperature(int temp), która wypisuje Thermostat set to [temp] degrees, oraz turnOff(), która wypisuje Thermostat turned OFF.

  • Commands.java: Utwórz konkretne klasy poleceń, które hermetyzują operacje na urządzeniach:

    TVOnCommand — przyjmuje obiekt Television w konstruktorze i podczas wykonania wywołuje powerOn().

    TVOffCommand — przyjmuje obiekt Television w konstruktorze i podczas wykonania wywołuje powerOff().

    TVChannelCommand — przyjmuje obiekt Television i wartość int channel w konstruktorze, a podczas wykonania wywołuje setChannel() z tym kanałem.

    ThermostatSetCommand — przyjmuje obiekt Thermostat i wartość int temperature w konstruktorze, a podczas wykonania wywołuje setTemperature() z tą wartością.

  • Main.java: Utwórz klasę RemoteControl (wywołujący) z metodą setCommand(Command cmd), która zapisuje polecenie, oraz metodą pressButton(), która wykonuje zapisane polecenie.

    W metodzie main otrzymasz dwa dane wejściowe: numer kanału telewizora (liczbę całkowitą) oraz temperaturę termostatu (liczbę całkowitą).

    Utwórz obiekt Television i obiekt Thermostat. Utwórz obiekt RemoteControl i zademonstruj wzorzec polecenia, wykonując następujące czynności:

    1. Ustaw TVOnCommand i naciśnij przycisk
    2. Ustaw TVChannelCommand z podanym numerem kanału i naciśnij przycisk
    3. Ustaw ThermostatSetCommand z podaną temperaturą i naciśnij przycisk
    4. Ustaw TVOffCommand i naciśnij przycisk

Otrzymasz kolejno dwa dane wejściowe: kanał telewizora (liczbę całkowitą) i temperaturę termostatu (liczbę całkowitą).

Na przykład dla danych wejściowych 5 i 72 wynik będzie następujący:

TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFF

Zauważ, że RemoteControl nigdy nie komunikuje się bezpośrednio z urządzeniami. Zna jedynie interfejs Command. Każde polecenie hermetyzuje wszystko, co jest potrzebne do wykonania jego działania, dzięki czemu można łatwo dodawać nowe urządzenia i polecenia bez zmieniania wywołującego!

Spróbuj swoich sił

import java.util.Scanner;

// TODO: Utwórz klasę RemoteControl (wywołującą) z:
// - metodą setCommand(Command cmd) do przechowywania polecenia
// - metodą pressButton() do wykonania zapisanego polecenia

class RemoteControl {
    // TODO: Zaimplementuj RemoteControl
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Odczytaj dane wejściowe
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Utwórz Television i Thermostat
        
        // TODO: Utwórz RemoteControl
        
        // TODO: Zademonstruj wzorzec Command:
        // 1. Ustaw TVOnCommand i naciśnij przycisk
        // 2. Ustaw TVChannelCommand z kanałem podanym na wejściu i naciśnij przycisk
        // 3. Ustaw ThermostatSetCommand z temperaturą podaną na wejściu i naciśnij przycisk
        // 4. Ustaw TVOffCommand i naciśnij przycisk
        
        scanner.close();
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Java online