Command, Chain of Responsibility e Template Method
I pattern comportamentali gestiscono la comunicazione e le responsabilità tra oggetti. Command incapsula richieste come oggetti (undo/redo), Chain of Responsibility passa richieste lungo una catena di handler (middleware), e Template Method definisce scheletri di algoritmi con passi personalizzabili.
🎯 Cosa Imparerai
- Command pattern: incapsulare azioni come oggetti
- Implementare undo/redo con Command
- Chain of Responsibility: catena di handler
- Template Method: algoritmi con hook points
Command Pattern
Il Command pattern incapsula una richiesta come un oggetto, permettendo di parametrizzare metodi con operazioni, mettere in coda richieste, e supportare operazioni annullabili (undo/redo).
// Interfaccia Command
interface Command {{ '{' }}
execute(): void;
undo(): void;
{{ '}' }}
// Receiver: oggetto che esegue l'azione reale
class Light {{ '{' }}
private isOn: boolean = false;
turnOn(): void {{ '{' }}
this.isOn = true;
console.log("💡 Luce accesa");
{{ '}' }}
turnOff(): void {{ '{' }}
this.isOn = false;
console.log("🌑 Luce spenta");
{{ '}' }}
getState(): boolean {{ '{' }}
return this.isOn;
{{ '}' }}
{{ '}' }}
// Concrete Commands
class TurnOnCommand implements Command {{ '{' }}
constructor(private light: Light) {{ '{' }}{{ '}' }}
execute(): void {{ '{' }}
this.light.turnOn();
{{ '}' }}
undo(): void {{ '{' }}
this.light.turnOff();
{{ '}' }}
{{ '}' }}
class TurnOffCommand implements Command {{ '{' }}
constructor(private light: Light) {{ '{' }}{{ '}' }}
execute(): void {{ '{' }}
this.light.turnOff();
{{ '}' }}
undo(): void {{ '{' }}
this.light.turnOn();
{{ '}' }}
{{ '}' }}
// Invoker: esegue i comandi
class RemoteControl {{ '{' }}
private history: Command[] = [];
executeCommand(command: Command): void {{ '{' }}
command.execute();
this.history.push(command);
{{ '}' }}
undo(): void {{ '{' }}
const command = this.history.pop();
if (command) {{ '{' }}
command.undo();
{{ '}' }}
{{ '}' }}
{{ '}' }}
// Utilizzo
const light = new Light();
const remote = new RemoteControl();
remote.executeCommand(new TurnOnCommand(light)); // "💡 Luce accesa"
remote.executeCommand(new TurnOffCommand(light)); // "🌑 Luce spenta"
remote.undo(); // "💡 Luce accesa" (annulla spegnimento)
Command con Undo/Redo Completo
Implementazione avanzata con undo/redo multipli:
class TextEditor {{ '{' }}
private content: string = "";
getContent(): string {{ '{' }}
return this.content;
{{ '}' }}
setContent(content: string): void {{ '{' }}
this.content = content;
{{ '}' }}
append(text: string): void {{ '{' }}
this.content += text;
{{ '}' }}
delete(length: number): void {{ '{' }}
this.content = this.content.slice(0, -length);
{{ '}' }}
{{ '}' }}
class AppendCommand implements Command {{ '{' }}
constructor(
private editor: TextEditor,
private text: string
) {{ '{' }}{{ '}' }}
execute(): void {{ '{' }}
this.editor.append(this.text);
{{ '}' }}
undo(): void {{ '{' }}
this.editor.delete(this.text.length);
{{ '}' }}
{{ '}' }}
class DeleteCommand implements Command {{ '{' }}
private deletedText: string = "";
constructor(
private editor: TextEditor,
private length: number
) {{ '{' }}{{ '}' }}
execute(): void {{ '{' }}
const content = this.editor.getContent();
this.deletedText = content.slice(-this.length);
this.editor.delete(this.length);
{{ '}' }}
undo(): void {{ '{' }}
this.editor.append(this.deletedText);
{{ '}' }}
{{ '}' }}
class CommandManager {{ '{' }}
private history: Command[] = [];
private redoStack: Command[] = [];
execute(command: Command): void {{ '{' }}
command.execute();
this.history.push(command);
this.redoStack = []; // Pulisci redo stack su nuova azione
{{ '}' }}
undo(): void {{ '{' }}
const command = this.history.pop();
if (command) {{ '{' }}
command.undo();
this.redoStack.push(command);
{{ '}' }}
{{ '}' }}
redo(): void {{ '{' }}
const command = this.redoStack.pop();
if (command) {{ '{' }}
command.execute();
this.history.push(command);
{{ '}' }}
{{ '}' }}
{{ '}' }}
// Utilizzo
const editor = new TextEditor();
const manager = new CommandManager();
manager.execute(new AppendCommand(editor, "Hello "));
manager.execute(new AppendCommand(editor, "World"));
console.log(editor.getContent()); // "Hello World"
manager.undo();
console.log(editor.getContent()); // "Hello "
manager.redo();
console.log(editor.getContent()); // "Hello World"
Chain of Responsibility Pattern
Il Chain of Responsibility permette a più oggetti di gestire una richiesta senza che il mittente conosca quale la gestirà. La richiesta passa lungo una catena finché qualcuno la gestisce.
// Handler astratto
abstract class Handler {{ '{' }}
protected next: Handler | null = null;
setNext(handler: Handler): Handler {{ '{' }}
this.next = handler;
return handler; // Fluent interface
{{ '}' }}
handle(request: string): void {{ '{' }}
if (this.canHandle(request)) {{ '{' }}
this.process(request);
{{ '}' }} else if (this.next) {{ '{' }}
this.next.handle(request);
{{ '}' }} else {{ '{' }}
console.log(`❌ Nessun handler per: 






