Command Pattern – Encapsulating Requests as Objects

Command Pattern – Encapsulating Requests as Objects

Design Patterns Series – Command Pattern

Turning Requests into Objects

In the previous article, we explored the Strategy Pattern, which helps select algorithms dynamically.

Now let's look at another powerful Behavioral Design Pattern that helps decouple the sender and receiver of a request.

Command Pattern

This pattern converts a request into an object, allowing you to parameterize clients with different requests, queue operations, and support undo/redo functionality.


What is the Command Pattern?

The Command Pattern encapsulates a request as an object, allowing you to pass it around like data.

Simple Definition

Command Pattern turns a request into a stand-alone object that contains all information about the request.

This includes:

• Method to call • Object that performs the action • Parameters for the operation


Real-World Example

Think about a remote control for a TV.

The remote control doesn’t directly know how the TV works internally.

Instead:

• Each button sends a command • The TV executes the command

Example:

• Power On • Power Off • Volume Up • Change Channel

Each of these actions is represented as a command object.


Command Pattern Structure

The pattern contains four main components.

1️⃣ Command Interface

Defines the method to execute a command.

2️⃣ Concrete Command

Implements the command interface and calls the receiver.

3️⃣ Receiver

The object that performs the actual work.

4️⃣ Invoker

The object that triggers the command.


Command Pattern – Kotlin Example

Let's implement a Smart Home Light Control System.


Step 1 – Command Interface

interface Command {
    fun execute()
}
        

Step 2 – Receiver

class Light {

    fun turnOn() {
        println("Light is ON")
    }

    fun turnOff() {
        println("Light is OFF")
    }
}
        

Step 3 – Concrete Commands

Turn On Command

class LightOnCommand(private val light: Light) : Command {

    override fun execute() {
        light.turnOn()
    }
}
        

Turn Off Command

class LightOffCommand(private val light: Light) : Command {

    override fun execute() {
        light.turnOff()
    }
}
        

Step 4 – Invoker (Remote Control)

class RemoteControl {

    private var command: Command? = null

    fun setCommand(command: Command) {
        this.command = command
    }

    fun pressButton() {
        command?.execute()
    }
}
        

Step 5 – Usage

fun main() {

    val light = Light()

    val lightOn = LightOnCommand(light)
    val lightOff = LightOffCommand(light)

    val remote = RemoteControl()

    remote.setCommand(lightOn)
    remote.pressButton()

    remote.setCommand(lightOff)
    remote.pressButton()
}
        

Output

Light is ON
Light is OFF
        

Command Pattern in Android

This pattern appears in many Android architectures.

Examples

1️⃣ Button Click Handlers

button.setOnClickListener { viewModel.submitOrder() }
        

The click action acts like a command.


2️⃣ Undo / Redo Systems

Used in:

• Drawing apps • Text editors • Image editors

Commands store operations that can be reversed.


3️⃣ Task Queues

Used in:

• Background jobs • Job scheduling • WorkManager tasks

Commands can be queued and executed later.


Benefits of Command Pattern

✔ Decouples sender and receiver ✔ Supports undo / redo functionality ✔ Enables request queuing ✔ Easy to extend new commands ✔ Improves code flexibility


When to Use Command Pattern

Use this pattern when:

• You want to parameterize objects with actions • You need undo / redo functionality • You want to queue or log requests • You want to decouple UI from business logic

Perfect for:

• UI event systems • Task schedulers • Macro recording • Transaction systems


Potential Drawbacks

⚠ Increased number of classes ⚠ Over-engineering for simple systems

But for complex systems, this pattern provides great flexibility and maintainability.


Final Thoughts

The Command Pattern is extremely useful when building systems that require flexible and reusable actions.

It allows developers to treat requests as objects, enabling powerful capabilities like undo operations, task scheduling, and command history.


Next in the Design Patterns Series

Next we will explore:

State Pattern – Changing Behavior Based on Object State

We’ll cover:

• Real-world examples • Kotlin implementation • Android use cases


#DesignPatterns #CommandPattern #Kotlin #AndroidDevelopment #SoftwareArchitecture #SystemDesign #CleanCode

To view or add a comment, sign in

More articles by Sangili Murugan V

Explore content categories