Skip to content

Latest commit

 

History

History
158 lines (119 loc) · 4.31 KB

File metadata and controls

158 lines (119 loc) · 4.31 KB

Command Pattern

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.

Overview

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 lets you parameterize methods with different requests, delay or queue a request's execution, and support undoable operations.

Structure

[Image: Command Pattern Class Diagram]
<!-- Add a class diagram image here -->

Components

  1. Command Interface

    • Declares an interface for executing an operation
    • Contains methods like execute() and undo()
  2. Concrete Commands

    • Implements the Command interface
    • Defines a binding between a Receiver object and an action
    • Implements execute() by invoking the corresponding operation(s) on the Receiver
  3. Receiver

    • Knows how to perform the operations associated with carrying out a request
    • Any class can serve as a Receiver
  4. Invoker

    • Asks the command to carry out the request
    • Holds commands and can execute them
    • Can also support undo operations

Implementation

Key Classes

  1. Command.java

    public interface Command {
        void execute();
        void undo();
        void show();
    }
  2. LightOnCommand.java and LightOffCommand.java

    • Concrete command implementations
    • Encapsulate the receiver (Light) and the action to perform
  3. Light.java

    • The receiver class
    • Knows how to perform the actual operations

Example Usage

// Create the receiver
Light light = new Light();

// Create the commands
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);

// Execute commands
lightOn.execute();  // Turns the light on
lightOff.execute(); // Turns the light off
lightOn.undo();     // Undoes the last command

Use Cases

The Command pattern is particularly useful when:

  1. You need to parameterize objects with operations
  2. You want to queue operations, schedule their execution, or execute them remotely
  3. You need to implement undo/redo functionality
  4. You want to structure a system around high-level operations
  5. You need to support logging and transactions

Benefits

  • Decouples the invoker from the receiver
  • Allows for command queuing and logging
  • Supports undo/redo operations
  • Enables the implementation of complex operations
  • Provides a way to parameterize clients with different requests

Drawbacks

  • Can lead to a large number of command classes
  • May increase the complexity of the code
  • Can be overkill for simple operations

Real-World Examples

  1. Text Editor

    • Undo/redo operations
    • Copy/paste commands
    • Formatting commands
  2. Remote Control

    • Button presses mapped to commands
    • Macro commands for multiple operations
    • Undo functionality
  3. Job Queue Systems

    • Command queuing
    • Asynchronous execution
    • Command logging

Related Patterns

  • Composite: Can be used to implement macro commands
  • Memento: Can be used to implement undo/redo
  • Observer: Can be used to implement command logging
  • Strategy: Similar in structure but different in intent

Best Practices

  1. Keep commands focused and simple
  2. Use the Command pattern when you need to:
    • Queue operations
    • Support undo/redo
    • Log operations
    • Implement remote execution
  3. Consider using the Composite pattern for macro commands
  4. Use the Memento pattern for implementing undo/redo
  5. Consider thread safety in multi-threaded environments

Testing

When testing Command pattern implementations:

  1. Test each command in isolation
  2. Verify undo/redo functionality
  3. Test command queuing
  4. Verify command logging
  5. Test macro commands
  6. Verify thread safety

Common Pitfalls

  1. Creating too many command classes
  2. Overcomplicating simple operations
  3. Not properly implementing undo/redo
  4. Ignoring thread safety
  5. Not considering command queuing
  6. Not implementing proper error handling

Future Improvements

  1. Add support for command queuing
  2. Implement command logging
  3. Add support for macro commands
  4. Implement remote execution
  5. Add support for command scheduling
  6. Implement command persistence