# CommandA intermediate-level guide to Command: before-and-after java code and diagrams for a CS student.

## The Overloaded Button

Imagine you are building a text editor. You have a `ToolbarButton` that needs to respond when a user clicks it. At first, it only needs to trigger one action: saving the document. But soon, the requirements grow. Now the button must also handle printing and deleting. 

In a naive implementation, the button becomes responsible for knowing exactly what every other part of the system does. It has to check which type of action was requested and then call the specific method on the `Document` object. This creates a "God Object" smell where the button is doing too much work—it is no longer just a UI trigger; it is now an orchestrator of business logic.

```java
class Document {
    void save() { System.out.println("Saving document..."); }
    void print() { System.out.println("Printing document..."); }
    void delete() { System.out.println("Deleting document..."); }
}

class ToolbarButton {
    private final Document doc;

    public ToolbarButton(Document doc) { this.doc = doc; }

    // The button must know about every specific operation of the Document.
    // Adding a new action requires modifying this class (violates Open/Closed).
    public void handleClick(String actionType) {
        if ("save".equals(actionType)) {
            doc.save();
        } else if ("print".equals(actionType)) {
            doc.print();
        } else if ("delete".equals(actionType)) {
            doc.delete();
        }
    }
}
```

As seen above, the `ToolbarButton` is tightly coupled to the `Document`. It must know that `save()`, `print()`, and `delete()` exist. If you add a "Format" feature, you have to go back into the button class and add another `else if` block. This violates the Open/Closed Principle, which states that classes should be open for extension but closed for modification.

```mermaid
classDiagram
    direction BT
    class ToolbarButton {
        +handleClick(String actionType)
    }
    class Document {
        +save()
        +print()
        +delete()
    }
    ToolbarButton ..> Document : calls methods via string check
```

## Turning Actions into Objects

To fix this, we use the Command pattern. Instead of passing a "request type" (like a String) to the button, we pass an object that represents the request itself. 

Think of a restaurant: A customer doesn't walk into a kitchen and start cooking; they hand a written order slip to a waiter. The waiter (the Invoker) doesn't need to know how to cook a steak; they only need to deliver that slip to the chef (the Receiver). Once the chef reads the slip, they perform the actual work.

In this pattern:
1.  The **Command** is the order slip (an interface with an `execute()` method).
2.  The **Invoker** is the waiter (`ToolbarButton`), which triggers the command.
3.  The **Receiver** is the chef (`Document`), who knows how to perform the actual work.

By treating the request as a standalone object, we achieve decoupling. The button no longer cares *what* happens when it is clicked; it only knows that it has an object with an `execute()` method.

```java
interface Command {
    void execute();
}

class Document {
    void save() { System.out.println("Saving document..."); }
    void print() { System.out.println("Printing document..."); }
    void delete() { System.out.println("Deleting document..."); }
}

// Concrete Command for saving
class SaveCommand implements Command {
    private final Document doc;
    public SaveCommand(Document doc) { this.doc = doc; }
    @Override public void execute() { doc.save(); }
}

// Concrete Command for printing
class PrintCommand implements Command {
    private final Document doc;
    public PrintCommand(Document doc) { this.doc = doc; }
    @Override public void execute() { doc.print(); }
}

// The ToolbarButton (Invoker) is now decoupled from the Document (Receiver).
// It only knows how to trigger a Command.
class ToolbarButton {
    private final Command command;

    public ToolbarButton(Command command) { this.command = command; }

    public void handleClick() {
        command.execute();
    }
}
```

Now, the relationship is transformed. The `ToolbarButton` interacts with an abstraction (`Command`) rather than a concrete implementation (`Document`). To add a new feature like "Format," you simply create a new class that implements the `Command` interface. You never have to touch the `ToolbarButton` code again.

```mermaid
classDiagram
    class Command {
        <<interface>>
        +execute()
    }
    class SaveCommand {
        -Document doc
        +execute()
    }
    class PrintCommand {
        -Document doc
        +execute()
    }
    class ToolbarButton {
        -Command command
        +handleClick()
    }
    class Document {
        +save()
        +print()
    }

    Command <|.. SaveCommand : implements
    Command <|.. PrintCommand : implements
    ToolbarButton o-- Command : holds reference to
    SaveCommand --> Document : calls
    PrintCommand --> Document : calls
```

When a user clicks the button, a specific sequence of events occurs. The button tells the command to execute, and that command then directs the receiver to perform its task:

```mermaid
sequenceDiagram
    participant B as ToolbarButton
    participant C as SaveCommand
    participant D as Document

    B ->> C: handleClick()
    C ->> C: execute()
    C ->> D: save()
    D -->> C: 
    C -->> B: 
```

## When to Use It, and When Not To

The Command pattern is powerful because it turns a method call into a first-class citizen. While this example shows basic execution, treating actions as objects allows you to do more advanced things, such as storing commands in a list to implement "Undo/Redo" functionality or placing them in a queue to be processed later.

However, there is a cost: complexity. Every new action now requires a new class. If your application only has two buttons that will never change, creating an interface and multiple concrete classes is likely overkill and introduces unnecessary boilerplate. Use Command when you need to decouple the trigger from the logic or when you need to manage the lifecycle of an action (like queuing or undoing it).

## Takeaways

- Use Command to turn a request into a standalone object.
- Decouple the "trigger" (Invoker) from the "doer" (Receiver).
- If a class is doing too many different things based on event types, it's time for Commands.

## Usage

**Using the decoupled commands**

```java
Document myDoc = new Document();
ToolbarButton saveBtn = new ToolbarButton(new SaveCommand(myDoc));
ToolbarButton printBtn = new ToolbarButton(new PrintCommand(myDoc));

saveBtn.handleClick();  // Output: Saving document...
printBtn.handleClick(); // Output: Printing document...
```
