Command
The Command pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. Essentially, it decouples the object that originates the request from the object that knows how to perform it.
This pattern promotes loose coupling and makes the system more flexible. It’s particularly useful when you need to manage a history of actions for undo/redo functionality, delay or queue the execution of a request, or when you want to combine basic operations into more complex ones.
Usage
The Command pattern is widely used in scenarios requiring transaction management, logging, and undo/redo capabilities. It’s core to many editor implementations, allowing for actions like copy, paste, and delete to be tracked and reversed. Modern frameworks often leverage the command pattern, either explicitly or implicitly, for event handling and asynchronous task processing. It’s also common in game development for handling player actions.
Examples
-
GUI Frameworks (e.g., Qt, Swing): Most GUI frameworks utilize the Command pattern for handling user interactions. When a user clicks a button, the framework creates a command object representing that action (e.g.,
FileOpenCommand,ButtonClickHandler). This command is then executed by a receiver (e.g., a file system or a widget). This allows for easy undo/redo functionality and event logging. -
Database Transactions: Database systems internally use a command pattern to manage transactions. Each SQL statement is treated as a command. These commands are bundled into a transaction, and the database engine can then commit or rollback the entire set of commands, ensuring data consistency. An example might be
UpdateAccountCommand,DeleteRecordCommand, associated with aTransactionManager. -
Undo/Redo Systems in Text Editors: Text editors like Notepad++ or VS Code use the command pattern so that actions like typing, deleting, or formatting text are all commands. These commands can be stored in a stack for undo/redo functionality. Each command holds enough information (e.g., the deleted text, the old formatting) to reverse its effect.
Specimens
15 implementationsThe Command Pattern encapsulates a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations. This implementation uses Dart’s function type and abstract class capabilities to define a command interface with an execute method. Concrete commands wrap specific operations on a SimpleEditor receiver. An EditorInvoker manages command execution and potentially queuing. Dart’s concise syntax and support for first-class functions make this pattern particularly clean to implement, avoiding excessive interface bloat often seen in other languages. The use of an abstract class provides type safety and a clear contract for all commands.
abstract class Command {
void execute();
void unexecute(); // Optional for undo functionality
}
class SimpleEditor {
String text = '';
void setText(String newText) {
text = newText;
print('Text set to: $text');
}
void appendText(String addedText) {
text += addedText;
print('Text appended: $text');
}
}
class SetTextCommand implements Command {
final SimpleEditor editor;
final String text;
String? previousText;
SetTextCommand(this.editor, this.text);
@override
void execute() {
previousText = editor.text;
editor.setText(text);
}
@override
void unexecute() {
editor.setText(previousText ?? ''); // Restore previous state
}
}
class AppendTextCommand implements Command {
final SimpleEditor editor;
final String text;
AppendTextCommand(this.editor, this.text);
@override
void execute() {
editor.appendText(text);
}
@override
void unexecute() {
// Simple un-append. More complex scenarios might need storing more state.
if (editor.text.endsWith(text)) {
editor.text = editor.text.substring(0, editor.text.length - text.length);
print('Text un-appended: ${editor.text}');
}
}
}
class EditorInvoker {
final List<Command> commands = [];
void executeCommand(Command command) {
command.execute();
commands.add(command);
}
void undoLastCommand() {
if (commands.isNotEmpty) {
final command = commands.removeLast();
command.unexecute();
} else {
print('No commands to undo.');
}
}
}
void main() {
final editor = SimpleEditor();
final invoker = EditorInvoker();
final setTextCommand = SetTextCommand(editor, 'Hello');
invoker.executeCommand(setTextCommand);
final appendCommand = AppendTextCommand(editor, ' World!');
invoker.executeCommand(appendCommand);
invoker.undoLastCommand();
invoker.undoLastCommand();
}
The Command pattern encapsulates a request as an object, allowing for parameterization of clients with different requests, queueing or logging of requests, and support for undoable operations. This Scala example uses a functional style with traits and case classes to define the command interface and concrete commands. Order is the invoker, accepting and executing OrderCommands. The Command trait defines the execute method. Idiomatic Scala is used with immutability (case classes) and leveraging functional composition to represent actions. No mutable state is used within the commands themselves, enhancing testability and concurrency.
trait Command {
def execute(): String
}
case class AddItemCommand(order: Order, item: String) extends Command {
override def execute(): String = {
order.addItem(item)
s"Added $item to the order."
}
}
case class RemoveItemCommand(order: Order, item: String) extends Command {
override def execute(): String = {
order.removeItem(item)
s"Removed $item from the order."
}
}
case class Order(items: List[String] = List.empty) {
def addItem(item: String): Order = Order(item :: items)
def removeItem(item: String): Order = Order(items.filter(_ != item))
def listItems():String = items.mkString(", ")
}
object CommandExample {
def main(args: Array[String]): Unit = {
val myOrder = Order()
val addItem1 = AddItemCommand(myOrder, "Shirt")
val addItem2 = AddItemCommand(myOrder, "Pants")
val removeItem = RemoveItemCommand(myOrder, "Shirt")
println(addItem1.execute())
println(addItem2.execute())
println(removeItem.execute())
println(s"Current order: ${myOrder.listItems()}")
}
}
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation uses PHP interfaces to define the Command and Receiver roles. Concrete commands like LightOnCommand and LightOffCommand encapsulate the action and the receiver (a Light object). An Invoker (e.g., a RemoteControl) then executes the commands without knowing the underlying operation. This conforms to PHP’s object-oriented style by leveraging interfaces and classes for clear separation of concerns and extensibility.
<?php
/**
* Receiver: Knows how to perform the action.
*/
class Light
{
public function on()
{
echo "Light is on.\n";
}
public function off()
{
echo "Light is off.\n";
}
}
/**
* Command: Declares an interface for executing a request.
*/
interface Command
{
public function execute();
public function undo(); // Optional
}
/**
* Concrete Command: Binds a receiver to an action.
*/
class LightOnCommand implements Command
{
private Light $light;
public function __construct(Light $light)
{
$this->light = $light;
}
public function execute()
{
$this->light->on();
}
public function undo()
{
$this->light->off();
}
}
/**
* Concrete Command: Binds a receiver to an action.
*/
class LightOffCommand implements Command
{
private Light $light;
public function __construct(Light $light)
{
$this->light = $light;
}
public function execute()
{
$this->light->off();
}
public function undo()
{
$this->light->on();
}
}
/**
* Invoker: Requests the command to execute.
*/
class RemoteControl
{
private Command $command;
public function setCommand(Command $command)
{
$this->command = $command;
}
public function buttonPressed()
{
$this->command->execute();
}
}
// Client code
$light = new Light();
$onCommand = new LightOnCommand($light);
$offCommand = new LightOffCommand($light);
$remote = new RemoteControl();
$remote->setCommand($onCommand);
$remote->buttonPressed();
$remote->setCommand($offCommand);
$remote->buttonPressed();
?>
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queueing or logging of requests, and support for undoable operations. This example represents simple calculator operations (add, subtract) as commands. Each command has an execute method that performs the operation on a Calculator receiver. The execute method stores the previous value enabling a simplistic undo functionality. Ruby’s flexibility lends itself well to this pattern; we utilize classes to represent commands, making them first-class objects, and the call method for a command-like interface, fitting with the language’s object-oriented nature.
# Receiver
class Calculator
attr_accessor :current
def initialize(current = 0)
@current = current
end
def add(value)
@previous = @current
@current += value
end
def subtract(value)
@previous = @current
@current -= value
end
def current_value
@current
end
end
# Command Interface
class Command
def initialize(calculator)
@calculator = calculator
end
def execute
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
def undo
#Basic Undo based on previous state. More complex undo could involve arguments.
@calculator.current = @calculator.previous if defined? @calculator.previous
end
end
# Concrete Commands
class AddCommand < Command
def initialize(calculator, value)
super(calculator)
@value = value
end
def execute
@calculator.add(@value)
end
end
class SubtractCommand < Command
def initialize(calculator, value)
super(calculator)
@value = value
end
def execute
@calculator.subtract(@value)
end
end
# Invoker
class Invoker
def initialize
@commands = []
end
def add_command(command)
@commands << command
end
def execute_commands
@commands.each do |command|
command.execute
end
end
def undo_all
@commands.reverse_each do |command|
command.undo
end
end
end
# Example Usage
calculator = Calculator.new
invoker = Invoker.new
add_command = AddCommand.new(calculator, 10)
subtract_command = SubtractCommand.new(calculator, 5)
invoker.add_command(add_command)
invoker.add_command(subtract_command)
invoker.execute_commands
puts "Current value: #{calculator.current_value}" # Output: Current value: 5
invoker.undo_all
puts "Current value after undo: #{calculator.current_value}" # Output: Current value after undo: 0
The Command pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. This implementation uses a protocol to define the command interface, with concrete commands implementing specific actions on a receiver object. The RemoteControl acts as the invoker, holding and executing commands. Swift’s protocol-oriented programming lends itself well to this pattern, as protocols naturally define interfaces, and functions can be passed as first-class citizens—effectively making them commands. Using a dictionary to map buttons to commands provides a flexible way to configure the remote.
// Command Protocol
protocol Command {
func execute()
}
// Receiver
class Light {
var isOn: Bool = false
func turnOn() {
isOn = true
print("Light turned on")
}
func turnOff() {
isOn = false
print("Light turned off")
}
}
// Concrete Commands
class TurnOnCommand: Command {
private let light: Light
init(light: Light) {
self.light = light
}
func execute() {
light.turnOn()
}
}
class TurnOffCommand: Command {
private let light: Light
init(light: Light) {
self.light = light
}
func execute() {
light.turnOff()
}
}
// Invoker
class RemoteControl {
private var commands: [String: Command] = [:]
func setCommand(button: String, command: Command) {
commands[button] = command
}
func buttonPressed(button: String) {
if let command = commands[button] {
command.execute()
} else {
print("No command assigned to button \(button)")
}
}
}
// Client Code
let light = Light()
let turnOnCommand = TurnOnCommand(light: light)
let turnOffCommand = TurnOffCommand(light: light)
let remote = RemoteControl()
remote.setCommand(button: "on", command: turnOnCommand)
remote.setCommand(button: "off", command: turnOffCommand)
remote.buttonPressed(button: "on")
remote.buttonPressed(button: "off")
remote.buttonPressed(button: "unknown")
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation features a Command interface defining an execute() method. Concrete commands like OpenCommand and CloseCommand implement this, holding a reference to the Document receiver. An App or RemoteControl class contains a command history and can execute commands.
Kotlin’s concise syntax and support for functional interfaces (like Command) makes implementing this pattern very natural. The use of data classes for commands allows for immutable command objects. The App class acting as an invoker leverages Kotlin’s ability to pass functions as first-class citizens, further enhancing the pattern’s flexibility.
// Command Interface
interface Command {
fun execute()
}
// Receiver
class Document {
var isOpen = false
fun open() {
isOpen = true
println("Document opened")
}
fun close() {
isOpen = false
println("Document closed")
}
}
// Concrete Commands
data class OpenCommand(private val document: Document) : Command {
override fun execute() {
document.open()
}
}
data class CloseCommand(private val document: Document) : Command {
override fun execute() {
document.close()
}
}
// Invoker (App/RemoteControl)
class App(private val document: Document) {
private val commandHistory = mutableListOf<Command>()
fun executeCommand(command: Command) {
command.execute()
commandHistory.add(command)
}
fun undo() {
if (commandHistory.isNotEmpty()) {
val lastCommand = commandHistory.removeLast()
// Simple undo - assumes command is its own inverse. More complex
// implementations would need to store undo operations.
if (lastCommand is OpenCommand) {
document.close()
println("Undoing open document")
} else if (lastCommand is CloseCommand) {
document.open()
println("Undoing close document")
}
} else {
println("No commands to undo")
}
}
}
fun main() {
val document = Document()
val app = App(document)
app.executeCommand(OpenCommand(document))
app.executeCommand(CloseCommand(document))
app.undo()
app.undo()
}
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation uses Rust’s FnOnce trait to define commands as closures that can be executed once. A CommandManager holds a vector of these commands and provides mechanisms to add and execute them. This approach leverages Rust’s ownership and borrowing rules to guarantee safety and prevents accidental re-execution of commands. The functional style is naturally suited to defining commands as closures.
// Define the Command trait using a closure that takes ownership of the receiver.
trait Command {
fn execute(&self);
}
// Implement Command for a simple struct. This is often where the actual work happens.
struct Receiver {
data: String,
}
impl Receiver {
fn operation(&mut self, input: &str) {
self.data = input.to_string();
}
}
// Example commands
struct AddCommand {
receiver: Receiver,
input: String,
}
impl AddCommand {
fn new(receiver: Receiver, input: String) -> Self {
AddCommand { receiver, input }
}
}
impl Command for AddCommand {
fn execute(&self) {
let mut receiver = self.receiver;
receiver.operation(&self.input);
println!("Added data: {}", self.input);
}
}
struct PrintCommand {
receiver: Receiver,
}
impl PrintCommand {
fn new(receiver: Receiver) -> Self {
PrintCommand { receiver }
}
}
impl Command for PrintCommand {
fn execute(&self) {
println!("Current data: {}", self.receiver.data);
}
}
// Command Manager
struct CommandManager {
commands: Vec<Box<dyn Command>>,
}
impl CommandManager {
fn new() -> Self {
CommandManager { commands: Vec::new() }
}
fn add_command(&mut self, command: Box<dyn Command>) {
self.commands.push(command);
}
fn execute_all(&mut self) {
for command in &mut self.commands {
command.execute();
}
self.commands.clear(); //Optional: clear commands after execution.
}
}
fn main() {
let mut receiver = Receiver { data: String::new() };
let mut command_manager = CommandManager::new();
command_manager.add_command(Box::new(AddCommand::new(receiver.clone(), "Hello".to_string())));
command_manager.add_command(Box::new(PrintCommand::new(receiver.clone())));
command_manager.add_command(Box::new(AddCommand::new(receiver.clone(), " World".to_string())));
command_manager.add_command(Box::new(PrintCommand::new(receiver.clone())));
command_manager.execute_all();
}
The Command pattern encapsulates a request as an object, allowing for parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This example defines a Command interface with an Execute method. Concrete commands like BuyCommand and SellCommand implement this interface, holding the necessary data to perform the action on a StockTrader receiver. An Invoker (broker) manages the commands and executes them. This Go implementation uses interfaces to define the command structure, making it flexible and testable, and aligns with Go’s preference for composition over inheritance.
// main.go
package main
import "fmt"
// Command interface
type Command interface {
Execute()
}
// StockTrader receiver
type StockTrader struct {
cash int
shares int
}
func (s *StockTrader) Buy(quantity, price int) {
cost := quantity * price
if s.cash >= cost {
s.cash -= cost
s.shares += quantity
fmt.Printf("Bought %d shares at %d. Cash: %d, Shares: %d\n", quantity, price, s.cash, s.shares)
} else {
fmt.Println("Insufficient funds")
}
}
func (s *StockTrader) Sell(quantity, price int) {
if s.shares >= quantity {
s.cash += quantity * price
s.shares -= quantity
fmt.Printf("Sold %d shares at %d. Cash: %d, Shares: %d\n", quantity, price, s.cash, s.shares)
} else {
fmt.Println("Insufficient shares")
}
}
// Concrete Commands
type BuyCommand struct {
trader *StockTrader
quantity int
price int
}
func (b *BuyCommand) Execute() {
b.trader.Buy(b.quantity, b.price)
}
type SellCommand struct {
trader *StockTrader
quantity int
price int
}
func (s *SellCommand) Execute() {
s.trader.Sell(s.quantity, s.price)
}
// Invoker / Broker
type Broker struct {
commands []Command
}
func (b *Broker) AddCommand(command Command) {
b.commands = append(b.commands, command)
}
func (b *Broker) ExecuteCommands() {
for _, command := range b.commands {
command.Execute()
}
}
func main() {
trader := &StockTrader{cash: 1000, shares: 0}
broker := &Broker{}
broker.AddCommand(&BuyCommand{trader: trader, quantity: 10, price: 50})
broker.AddCommand(&SellCommand{trader: trader, quantity: 5, price: 60})
broker.AddCommand(&BuyCommand{trader: trader, quantity: 20, price: 40}) // Might fail
broker.ExecuteCommands()
}
The Command pattern encapsulates a request as an object, allowing for parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation defines a base command struct with an execute function pointer. Concrete commands implement this interface to perform specific actions on a receiver object. An invoker holds and executes commands. This approach is idiomatic C as it leverages function pointers to achieve polymorphism and avoids complex object hierarchies, keeping the code lightweight and efficient.
#include <stdio.h>
#include <stdlib.h>
// Receiver
typedef struct {
int value;
} Receiver;
void receiver_set_value(Receiver *receiver, int value) {
receiver->value = value;
}
int receiver_get_value(const Receiver *receiver) {
return receiver->value;
}
// Command
typedef struct {
Receiver *receiver;
void (*execute)(const struct Command*);
} Command;
// Concrete Commands
void command_set_a(const Command *command) {
receiver_set_value(command->receiver, 10);
}
void command_set_b(const Command *command) {
receiver_set_value(command->receiver, 20);
}
// Invoker
typedef struct {
Command *command;
} Invoker;
void invoker_set_command(Invoker *invoker, Command *command) {
invoker->command = command;
}
void invoker_execute_command(Invoker *invoker) {
if (invoker->command != NULL) {
invoker->command->execute(invoker->command);
}
}
int main() {
Receiver receiver = {0};
Invoker invoker;
Command set_a_command = {&receiver, command_set_a};
Command set_b_command = {&receiver, command_set_b};
invoker_set_command(&invoker, &set_a_command);
invoker_execute_command(&invoker);
printf("Value after set A: %d\n", receiver_get_value(&receiver));
invoker_set_command(&invoker, &set_b_command);
invoker_execute_command(&invoker);
printf("Value after set B: %d\n", receiver_get_value(&receiver));
return 0;
}
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queue or log requests, and support undoable operations. This implementation uses C++ classes to represent concrete commands, an interface for commands, and an invoker class that manages command execution. It’s idiomatic C++ due to its explicit use of classes, interfaces (abstract classes), and pointers to objects, leveraging polymorphism for flexible command handling. The ’execute’ method within the Command interface is a key element, adhering to the principle of separating the request from its execution.
#include <iostream>
#include <memory>
// Command Interface
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// Receiver
class Light {
public:
void turnOn() {
std::cout << "Light turned on" << std::endl;
}
void turnOff() {
std::cout << "Light turned off" << std::endl;
}
};
// Concrete Commands
class TurnOnCommand : public Command {
public:
TurnOnCommand(Light* light) : light_(light) {}
void execute() override {
light_->turnOn();
}
private:
Light* light_;
};
class TurnOffCommand : public Command {
public:
TurnOffCommand(Light* light) : light_(light) {}
void execute() override {
light_->turnOff();
}
private:
Light* light_;
};
// Invoker
class SimpleRemoteControl {
public:
void setCommand(std::unique_ptr<Command> command) {
command_ = std::move(command);
}
void buttonPressed() {
if (command_) {
command_->execute();
} else {
std::cout << "No command set." << std::endl;
}
}
private:
std::unique_ptr<Command> command_;
};
int main() {
Light* light = new Light();
SimpleRemoteControl remote;
remote.setCommand(std::make_unique<TurnOnCommand>(light));
remote.buttonPressed();
remote.setCommand(std::make_unique<TurnOffCommand>(light));
remote.buttonPressed();
delete light; //explicit memory management
return 0;
}
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation defines a base Command class with an Execute method. Concrete commands like FileSaveCommand and FileOpenCommand implement this interface, holding the necessary data to perform the action. An Invoker class stores and executes commands. This is idiomatic C# due to the use of interfaces for abstraction, delegates (implicitly used within the command’s execution) and clear separation of concerns, fitting well into the language’s object-oriented structure.
// Command Pattern in C#
// Receiver - The object that knows how to perform the action
public class FileSystemReceiver
{
public string FilePath { get; set; }
public void OpenFile(string filePath)
{
FilePath = filePath;
Console.WriteLine($"Opening file: {filePath}");
}
public void SaveFile(string filePath)
{
FilePath = filePath;
Console.WriteLine($"Saving file to: {filePath}");
}
}
// Command Interface
public interface ICommand
{
void Execute();
}
// Concrete Commands
public class FileOpenCommand : ICommand
{
private readonly FileSystemReceiver _receiver;
private readonly string _filePath;
public FileOpenCommand(FileSystemReceiver receiver, string filePath)
{
_receiver = receiver;
_filePath = filePath;
}
public void Execute()
{
_receiver.OpenFile(_filePath);
}
}
public class FileSaveCommand : ICommand
{
private readonly FileSystemReceiver _receiver;
private readonly string _filePath;
public FileSaveCommand(FileSystemReceiver receiver, string filePath)
{
_receiver = receiver;
_filePath = filePath;
}
public void Execute()
{
_receiver.SaveFile(_filePath);
}
}
// Invoker - Stores and executes commands
public class Menu
{
private readonly List<ICommand> _commands = new List<ICommand>();
public void AddCommand(ICommand command)
{
_commands.Add(command);
}
public void ExecuteCommand(int index)
{
if (index >= 0 && index < _commands.Count)
{
_commands[index].Execute();
}
else
{
Console.WriteLine("Invalid command index.");
}
}
}
// Client
public class Program
{
public static void Main(string[] args)
{
FileSystemReceiver fileSystem = new FileSystemReceiver();
Menu menu = new Menu();
menu.AddCommand(new FileOpenCommand(fileSystem, "document.txt"));
menu.AddCommand(new FileSaveCommand(fileSystem, "document.txt"));
menu.ExecuteCommand(0); // Open file
menu.ExecuteCommand(1); // Save file
}
}
The Command pattern encapsulates a request as an object, thereby allowing clients to parameterize simple operations with various actions, queue or log requests, and support undoable operations. This implementation uses TypeScript’s type system and classes to define a command interface and concrete commands for basic calculator operations. A Calculator class acts as the receiver, performing the operations. The CommandInvoker (here, the Calculator instance itself) holds and executes commands. This is idiomatic TypeScript due to its use of interfaces for abstraction and classes for clear structure and type safety, enabling easy extensibility with new commands without modifying existing code.
// Command Interface
interface Command {
execute(): void;
undo(): void;
}
// Receiver
class Calculator {
private currentValue: number = 0;
add(amount: number): void {
this.currentValue += amount;
}
subtract(amount: number): void {
this.currentValue -= amount;
}
getCurrentValue(): number {
return this.currentValue;
}
}
// Concrete Commands
class AddCommand implements Command {
private amount: number;
private calculator: Calculator;
private previousValue: number;
constructor(calculator: Calculator, amount: number) {
this.calculator = calculator;
this.amount = amount;
this.previousValue = calculator.getCurrentValue();
}
execute(): void {
this.calculator.add(this.amount);
}
undo(): void {
this.calculator.add(-this.amount);
}
}
class SubtractCommand implements Command {
private amount: number;
private calculator: Calculator;
private previousValue: number;
constructor(calculator: Calculator, amount: number) {
this.calculator = calculator;
this.amount = amount;
this.previousValue = calculator.getCurrentValue();
}
execute(): void {
this.calculator.subtract(this.amount);
}
undo(): void {
this.calculator.add(this.amount);
}
}
// Usage
const calculator = new Calculator();
const addCommand = new AddCommand(calculator, 10);
const subtractCommand = new SubtractCommand(calculator, 5);
addCommand.execute();
console.log("After add:", calculator.getCurrentValue());
subtractCommand.execute();
console.log("After subtract:", calculator.getCurrentValue());
subtractCommand.undo();
console.log("After subtract undo:", calculator.getCurrentValue());
The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queue or log requests, and support undoable operations. This implementation uses a simple Command interface with an execute method. Concrete commands (like AddCommand, SubtractCommand) implement this interface, holding the necessary data to perform the operation. An Invoker (Calculator) takes and stores commands, delegating execution to them. This is idiomatic JavaScript by leveraging its flexible object and function-as-first-class-citizen nature. The use of functions as command objects simplifies the code and avoids the need for complex class hierarchies often seen in statically-typed languages.
// Command Interface
class Command {
constructor(receiver, action, operand) {
this.receiver = receiver;
this.action = action;
this.operand = operand;
}
execute() {
this.receiver[this.action](this.operand);
}
}
// Receiver
class Calculator {
constructor() {
this.value = 0;
}
add(operand) {
this.value += operand;
console.log(`Added ${operand}, value is now ${this.value}`);
}
subtract(operand) {
this.value -= operand;
console.log(`Subtracted ${operand}, value is now ${this.value}`);
}
getValue() {
return this.value;
}
}
// Invoker
class CommandInvoker {
constructor() {
this.commands = [];
}
addCommand(command) {
this.commands.push(command);
}
executeCommands() {
for (const command of this.commands) {
command.execute();
}
}
}
// Usage
const calculator = new Calculator();
const invoker = new CommandInvoker();
const addCommand1 = new Command(calculator, 'add', 10);
const subtractCommand = new Command(calculator, 'subtract', 5);
const addCommand2 = new Command(calculator, 'add', 2);
invoker.addCommand(addCommand1);
invoker.addCommand(subtractCommand);
invoker.addCommand(addCommand2);
invoker.executeCommands();
console.log("Final value:", calculator.getValue());
The Command pattern encapsulates a request as an object, allowing for parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation defines a Command interface with an execute method. Concrete commands like AddCommand and SubtractCommand implement this interface, holding the necessary data to perform the operation. An Invoker class manages these commands, allowing execution without knowing the specific operation. This fits Python’s duck typing well, as the invoker simply calls execute on any object that provides the method, supporting flexibility and loose coupling.
# command.py
from abc import ABC, abstractmethod
class Command(ABC):
@abstractmethod
def execute(self):
pass
class AddCommand(Command):
def __init__(self, calculator, value):
self.calculator = calculator
self.value = value
def execute(self):
self.calculator.add(self.value)
class SubtractCommand(Command):
def __init__(self, calculator, value):
self.calculator = calculator
self.value = value
def execute(self):
self.calculator.subtract(self.value)
class Calculator:
def __init__(self):
self.current_value = 0
def add(self, value):
self.current_value += value
print(f"Added {value}, current value: {self.current_value}")
def subtract(self, value):
self.current_value -= value
print(f"Subtracted {value}, current value: {self.current_value}")
def get_value(self):
return self.current_value
class Invoker:
def __init__(self):
self.commands = []
def set_command(self, command):
self.commands.append(command)
def execute_commands(self):
for command in self.commands:
command.execute()
if __name__ == '__main__':
calculator = Calculator()
invoker = Invoker()
invoker.set_command(AddCommand(calculator, 10))
invoker.set_command(SubtractCommand(calculator, 5))
invoker.set_command(AddCommand(calculator, 2))
invoker.execute_commands()
print(f"Final value: {calculator.get_value()}")
The Command pattern encapsulates a request as an object, thereby allowing for parameterization of clients with different requests, queuing or logging of requests, and support for undoable operations. This implementation defines a Command interface with an execute method. Concrete commands like TurnOnCommand and TurnOffCommand implement this interface, holding a reference to the Light (the receiver). The RemoteControl acts as the invoker, accepting and executing commands. This aligns with Java’s OOP principles promoting loose coupling and extensibility. Using interfaces and concrete classes is a standard Java approach for achieving polymorphism and a clean design.
// Command Interface
interface Command {
void execute();
}
// Receiver
class Light {
private boolean on;
public void turnOn() {
on = true;
System.out.println("Light is on");
}
public void turnOff() {
on = false;
System.out.println("Light is off");
}
public boolean isOn() {
return on;
}
}
// Concrete Commands
class TurnOnCommand implements Command {
private final Light light;
public TurnOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class TurnOffCommand implements Command {
private final Light light;
public TurnOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
// Invoker
class RemoteControl {
private Command slot;
public RemoteControl() {
}
public void setCommand(Command command) {
this.slot = command;
}
public void buttonPressed() {
slot.execute();
}
}
// Main
public class CommandExample {
public static void main(String[] args) {
Light light = new Light();
TurnOnCommand turnOn = new TurnOnCommand(light);
TurnOffCommand turnOff = new TurnOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(turnOn);
remote.buttonPressed(); // Light is on
remote.setCommand(turnOff);
remote.buttonPressed(); // Light is off
}
}