Introduction
The Command pattern is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation allows for parameterizing methods with different requests, delaying or queuing a request's execution, and supporting undoable operations.
Key Concepts
- Command: An interface or abstract class that declares a method for executing a command.
- ConcreteCommand: A class that implements the Command interface and defines the binding between a Receiver object and an action.
- Receiver: The object that performs the actual work when the command's execute method is called.
- Invoker: The object that knows how to execute a command but doesn't know how the command has been implemented.
- Client: The object that creates a ConcreteCommand and sets its receiver.
Structure
Here's a UML diagram of the Command pattern:
Components
-
Command Interface
public interface Command { void execute(); }
-
ConcreteCommand
public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } }
-
Receiver
public class Light { public void on() { System.out.println("The light is on"); } public void off() { System.out.println("The light is off"); } }
-
Invoker
public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); } }
-
Client
public class Client { public static void main(String[] args) { Light light = new Light(); Command lightOn = new LightOnCommand(light); RemoteControl remote = new RemoteControl(); remote.setCommand(lightOn); remote.pressButton(); } }
Example Explained
- Command Interface: The
Command
interface declares anexecute
method. - ConcreteCommand: The
LightOnCommand
class implements theCommand
interface and binds theLight
receiver to theon
action. - Receiver: The
Light
class contains the actual business logic to turn the light on and off. - Invoker: The
RemoteControl
class holds a command and triggers its execution. - Client: The
Client
class creates the receiver, binds it to a command, and sets the command in the invoker.
Practical Exercise
Task
Create a command pattern implementation for a simple text editor that supports the following operations:
- Write text
- Undo the last operation
Solution
-
Command Interface
public interface Command { void execute(); void undo(); }
-
ConcreteCommand
public class WriteCommand implements Command { private String text; private StringBuilder document; public WriteCommand(StringBuilder document, String text) { this.document = document; this.text = text; } @Override public void execute() { document.append(text); } @Override public void undo() { document.delete(document.length() - text.length(), document.length()); } }
-
Receiver
public class Document { private StringBuilder content = new StringBuilder(); public void write(String text) { content.append(text); } public void undoWrite(String text) { content.delete(content.length() - text.length(), content.length()); } public String getContent() { return content.toString(); } }
-
Invoker
public class TextEditor { private Command command; public void setCommand(Command command) { this.command = command; } public void type() { command.execute(); } public void undo() { command.undo(); } }
-
Client
public class Client { public static void main(String[] args) { Document document = new Document(); Command writeHello = new WriteCommand(document.getContent(), "Hello "); Command writeWorld = new WriteCommand(document.getContent(), "World!"); TextEditor editor = new TextEditor(); editor.setCommand(writeHello); editor.type(); System.out.println(document.getContent()); editor.setCommand(writeWorld); editor.type(); System.out.println(document.getContent()); editor.undo(); System.out.println(document.getContent()); } }
Explanation
- Command Interface: The
Command
interface now includes anundo
method. - ConcreteCommand: The
WriteCommand
class implements theCommand
interface and provides the logic for writing and undoing text. - Receiver: The
Document
class contains the actual text and methods to modify it. - Invoker: The
TextEditor
class holds a command and triggers its execution or undo. - Client: The
Client
class creates the receiver, binds it to commands, and sets the commands in the invoker.
Common Mistakes and Tips
- Mistake: Forgetting to implement the
undo
method in theConcreteCommand
.- Tip: Always ensure that both
execute
andundo
methods are implemented to maintain consistency.
- Tip: Always ensure that both
- Mistake: Directly modifying the receiver in the invoker.
- Tip: The invoker should only call the command's
execute
orundo
methods, not modify the receiver directly.
- Tip: The invoker should only call the command's
Conclusion
The Command pattern is a powerful tool for decoupling the sender and receiver of a request, allowing for flexible and reusable code. By encapsulating requests as objects, you can easily parameterize methods, queue requests, and implement undoable operations. This pattern is particularly useful in scenarios like GUI buttons, menu actions, and text editors.
In the next topic, we will explore the Interpreter pattern, which is another behavioral design pattern that deals with defining a grammar for a language and interpreting sentences in that language.
Software Design Patterns Course
Module 1: Introduction to Design Patterns
- What are Design Patterns?
- History and Origin of Design Patterns
- Classification of Design Patterns
- Advantages and Disadvantages of Using Design Patterns
Module 2: Creational Patterns
Module 3: Structural Patterns
Module 4: Behavioral Patterns
- Introduction to Behavioral Patterns
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Module 5: Application of Design Patterns
- How to Select the Right Pattern
- Practical Examples of Pattern Usage
- Design Patterns in Real Projects
- Refactoring Using Design Patterns
Module 6: Advanced Design Patterns
- Design Patterns in Modern Architectures
- Design Patterns in Microservices
- Design Patterns in Distributed Systems
- Design Patterns in Agile Development