Pattern Command
Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 70 di 87.
Il Command Pattern è un pattern di progettazione comportamentale che trasforma una richiesta in un oggetto autonomo contenente tutte le informazioni sulla richiesta. Questa trasformazione ti permette di passare le richieste come argomenti dei metodi, ritardare o mettere in coda l'esecuzione di una richiesta e supportare operazioni annullabili.
Pensala come un ristorante: invece di dire direttamente allo chef cosa cucinare, scrivi il tuo ordine su un foglietto. Il cameriere (invocatore) porta il foglietto (comando) in cucina, dove può essere messo in coda, avere la priorità o persino essere annullato. Il pattern disaccoppia l’oggetto che invoca l’operazione da quello che la esegue.
Il pattern ha quattro componenti chiave: un’interfaccia Command che dichiara il metodo execute, classi ConcreteCommand che implementano azioni specifiche, un Receiver che esegue il lavoro effettivo e un Invoker che attiva i comandi:
interface Command {
void execute();
}class Light { // Ricevitore
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 { // Invoker
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}L'invocatore non sa quale azione verrà eseguita. Si limita a chiamare execute():
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // Output: la luce è accesaIl pattern Command eccelle quando devi mettere in coda delle operazioni, implementare la funzionalità di annullamento/ripristino o pianificare attività da eseguire in un secondo momento. Ogni comando incapsula tutto ciò che serve per eseguire un'azione, rendendo il tuo sistema più flessibile ed estensibile.
Sfida
FacileCostruiamo un sistema di domotica intelligente usando il Pattern Command! Creerai un sistema in cui vari dispositivi domestici possono essere controllati tramite comandi, consentendo di accodare ed eseguire azioni e persino di memorizzarle per un uso successivo, proprio come un telecomando universale che non deve sapere come funziona internamente ciascun dispositivo.
Organizzerai il codice in quattro file:
Command.java: Definisci l'interfacciaCommandche tutti i comandi dei dispositivi implementeranno. Deve dichiarare un unico metodoexecute()che esegue l'azione del comando.Devices.java: Crea due classi ricevitore che rappresentano i dispositivi domestici intelligenti:Television- ha i metodipowerOn()che stampaTV is now ON,powerOff()che stampaTV is now OFFesetChannel(int channel)che stampaTV channel set to [channel].Thermostat- ha i metodisetTemperature(int temp)che stampaThermostat set to [temp] degreeseturnOff()che stampaThermostat turned OFF.Commands.java: Crea classi concrete di comandi che incapsulano le operazioni dei dispositivi:TVOnCommand- riceve unTelevisionnel costruttore e chiamapowerOn()quando viene eseguito.TVOffCommand- riceve unTelevisionnel costruttore e chiamapowerOff()quando viene eseguito.TVChannelCommand- riceve unTelevisione unint channelnel costruttore e chiamasetChannel()con quel canale quando viene eseguito.ThermostatSetCommand- riceve unThermostate unint temperaturenel costruttore e chiamasetTemperature()con quel valore quando viene eseguito.Main.java: Crea una classeRemoteControl(l'invocatore) che ha un metodosetCommand(Command cmd)per memorizzare un comando epressButton()per eseguire il comando memorizzato.Nel metodo principale, riceverai due input: il numero del canale TV (intero) e la temperatura del termostato (intero).
Crea un
Televisione unThermostat. Crea unRemoteControle mostra il Pattern Command:- Impostare un
TVOnCommande premere il pulsante - Impostare un
TVChannelCommandcon il canale inserito e premere il pulsante - Impostare un
ThermostatSetCommandcon la temperatura inserita e premere il pulsante - Impostare un
TVOffCommande premere il pulsante
- Impostare un
Riceverai due input nell'ordine seguente: il canale TV (intero) e la temperatura del termostato (intero).
Ad esempio, con gli input 5 e 72, il risultato sarà:
TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFFNota che RemoteControl non interagisce mai direttamente con i dispositivi. Conosce solo l'interfaccia Command. Ogni comando incapsula tutto ciò che serve per eseguire la propria azione, rendendo facile aggiungere nuovi dispositivi e comandi senza modificare l'invocatore!
Provalo tu
import java.util.Scanner;
// TODO: Crea la classe RemoteControl (l'invocatore) con:
// - il metodo setCommand(Command cmd) per memorizzare un comando
// - il metodo pressButton() per eseguire il comando memorizzato
class RemoteControl {
// TODO: Implementa RemoteControl
}
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leggi i valori di input
int channel = scanner.nextInt();
int temperature = scanner.nextInt();
// TODO: Crea un Television e un Thermostat
// TODO: Crea un RemoteControl
// TODO: Illustra il Command Pattern:
// 1. Imposta un TVOnCommand e premi il pulsante
// 2. Imposta un TVChannelCommand con il canale di input e premi il pulsante
// 3. Imposta un ThermostatSetCommand con la temperatura di input e premi il pulsante
// 4. Imposta un TVOffCommand e premi il pulsante
scanner.close();
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online