Pattern del Comando
Fa parte della sezione Programmazione orientata agli oggetti del percorso C# di Coddy. Lezione 56 di 70.
Il pattern Command è un pattern comportamentale che trasforma una richiesta in un oggetto autonomo contenente tutte le informazioni sulla richiesta. Questa trasformazione ti consente di passare le richieste come argomenti dei metodi, metterle in coda, registrarle o supportare operazioni annullabili.
Il pattern separa l'oggetto che invoca un'operazione dall'oggetto che sa come eseguirla. È composto da quattro componenti fondamentali: un'interfaccia di comando, comandi concreti, un ricevitore (l'oggetto che svolge il lavoro vero e proprio) e un invocatore (l'oggetto che attiva i comandi).
public interface ICommand
{
void Execute();
}
public class Light // Ricevitore
{
public void TurnOn() => Console.WriteLine("Light is ON");
public void TurnOff() => Console.WriteLine("Light is OFF");
}
public class TurnOnCommand : ICommand
{
private Light _light;
public TurnOnCommand(Light light) => _light = light;
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private Light _light;
public TurnOffCommand(Light light) => _light = light;
public void Execute() => _light.TurnOff();
}L'invocatore memorizza ed esegue i comandi senza sapere cosa fanno:
public class RemoteControl // Invocatore
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
}
// Utilizzo
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton(); // Light è ON
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton(); // Light è OFFIl pattern Command è particolarmente utile per implementare la funzionalità di annullamento, registrare macro o accodare operazioni per eseguirle in un secondo momento. Ogni comando incapsula tutto ciò che serve per eseguire un’azione, rendendo il tuo sistema più flessibile ed estensibile.
Sfida
FacileCreiamo un sistema di comandi per un editor di testo usando il pattern Command. Creerai un sistema in cui le operazioni di modifica, come l’inserimento e l’eliminazione di testo, sono incapsulate in oggetti comando, consentendo all’editor di eseguirle tramite un’interfaccia unificata.
Organizzerai il codice in tre file:
Command.cs: Definisci un’interfacciaICommandnello spazio dei nomiTextEditorcon un solo metodoExecute(). Poi crea due classi comando concrete:InsertCommand- accetta unDocumente una stringatextnel costruttore. Quando viene eseguito, aggiunge il testo al documento e stampaInserted: {text}DeleteCommand- accetta unDocumente unint countnel costruttore. Quando viene eseguito, rimuove dal documento gli ultimicountcaratteri e stampaDeleted: {count} characters
Document.cs: Crea una classeDocumentnello stesso spazio dei nomi. Questo è il ricevitore: l’oggetto che esegue effettivamente le operazioni sul testo. Dovrebbe avere:- Un campo stringa privato per memorizzare il contenuto (inizializzato come stringa vuota)
- Un metodo
Append(string text)che aggiunge testo al contenuto - Un metodo
RemoveLast(int count)che rimuove gli ultimicountcaratteri (se count supera la lunghezza del contenuto, cancella tutto il contenuto) - Un metodo
GetContent()che restituisce il contenuto corrente
Program.cs: Crea una classeEditorche funge da invocatore. Dovrebbe avere un metodoSetCommand(ICommand command)e un metodoExecuteCommand()che esegue il comando corrente. Nel codice principale, mostra il pattern Command elaborando una serie di operazioni di modifica.
Riceverai i seguenti input:
- Numero di comandi da eseguire
- Per ogni comando: il tipo di comando (
insertodelete) seguito dal testo da inserire oppure dal numero di caratteri da eliminare
Dopo aver eseguito tutti i comandi, stampa il contenuto finale del documento su una nuova riga nel formato Content: {content}.
Per esempio, se gli input sono:
4
insert
Hello
insert
World
delete
3
insert
!L’output dovrebbe essere:
Inserted: Hello
Inserted: World
Deleted: 3 characters
Inserted: !
Content: Hello Wo!Nota che Editor (l’invocatore) non sa nulla della manipolazione del testo: si limita a eseguire qualsiasi comando gli venga assegnato. I comandi incapsulano sia l’azione sia il ricevitore, rendendo facile aggiungere nuove operazioni come ReplaceCommand senza modificare l’editor!
Provalo tu
using System;
using TextEditor;
// TODO: Crea la classe Editor (l'invocatore)
public class Editor
{
// TODO: Aggiungi un campo privato per memorizzare il comando corrente
private ICommand _command;
// TODO: Implementa il metodo SetCommand
public void SetCommand(ICommand command)
{
// TODO: Memorizza il comando
}
// TODO: Implementa il metodo ExecuteCommand
public void ExecuteCommand()
{
// TODO: Esegui il comando corrente
}
}
class Program
{
public static void Main(string[] args)
{
// Leggi il numero di comandi
int n = Convert.ToInt32(Console.ReadLine());
// Crea il documento (il ricevitore)
Document document = new Document();
// Crea l'editor (l'invocatore)
Editor editor = new Editor();
// TODO: Elabora ogni comando
for (int i = 0; i < n; i++)
{
string commandType = Console.ReadLine();
// TODO: In base a commandType, crea il comando appropriato
// - Se "insert": leggi il testo e crea InsertCommand
// - Se "delete": leggi il numero e crea DeleteCommand
// Poi imposta il comando nell'editor ed eseguilo
}
// TODO: Stampa il contenuto finale nel formato "Content: {content}"
}
}
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 orientata agli oggetti
File esterniNamespace e direttiveIntroduzione a classi e oggettiLa parola chiave "this"Metodi e parametriCampi e proprietàCostruttoriInizializzatori di oggettiRiepilogo - Calcolatrice semplice4Ereditarietà
Sintassi di base dell'ereditarietà (:)La parola chiave 'base'Parole chiave virtual e overrideClassi sealedLa classe base 'object'Riepilogo - Gerarchia dei dipendenti7Funzionalità avanzate
Sovraccarico degli operatoriIndicizzatori (this[])Override di ToString()Metodi di estensioneRiepilogo - Lista personalizzata10Pattern di progettazione Parte 1
Introduzione ai pattern di progettazioneSingleton thread-safePattern FactoryPattern Observer (eventi)Pattern Strategy2Proprietà e membri statici
Proprietà implementate automaticamenteProprietà di sola lettura e di sola scritturaCampi e metodi staticiClassi staticheMembri con corpo di espressione5Polimorfismo e interfacce
Polimorfismo a compile time e runtimeInterfaccia o classe astrattaInterfacce multipleInterfacce espliciteUpcasting e downcastingRipasso: calcolatore di forme8Concetti avanzati di programmazione a oggetti
Composizione invece dell'ereditarietàTipi generici (classi e metodi)Delegati ed eventiAttributi e reflectionIDisposable e istruzione usingNozioni di base sull'iniezione delle dipendenze11Pattern di progettazione, parte 2
Pattern del ComandoPattern dell’AdattatorePattern del DecoratorePattern Template MethodPattern dello StatoPattern Composito3Architettura delle classi
Dati di istanza vs staticiParole chiave 'readonly' e 'const'Campi di supportoRiepilogo - Gestore di conti bancari6Incapsulamento
Modificatori di accessoProprietà per l'incapsulamentoImplementazione dell'occultamento dei datiModelli di immutabilitàRiepilogo - Registri degli studentiEsercitati da solo: Compilatore C# online