Understanding the Command Design Pattern

Share this article

Key Takeaways

  • The Command Pattern, also known as the Action or Transaction Pattern, encapsulates a request as an object, enabling the queuing or logging of clients with different requests. It’s a useful design pattern for implementing a command queue where requests can be queued for sequential processing, while decoupling the execution’s actual implementation from the queue itself.
  • In the context of a scenario where a message needs to be sent via different channels (email and SMS) to different user groups, the Command Pattern offers a unified approach. It allows for the retrieval of all customers from a database, instantiation of the appropriate IMessage implementations regardless of the customers’ communication preferences, and processing them once, instead of repeating the process for each group.
  • The Command Pattern is well suited for situations where you want to parameterize objects by an action to perform, need to specify, queue, and execute requests at different times, or when a set of changes to data need to be encapsulated as a single action (i.e. a transaction).
Did you know there are over 4 billion mobile phones in use today? Here in Australia, we have a population of approximately 11 million people and over 22 million mobile phones – that’s an average of 2 phones per person! It’s obvious that mobile phone usage is becoming more prevalent. And given the ubiquity of smartphones and other mobile devices, more and more customers are now opting to receive notifications via SMS rather than email. Text messages certainly have advantages over email – they’re short, immediate, and best of all SPAM is negligible. So, what does this have to do with the Command Pattern you ask? Well, let’s look at an imaginary scenario. A company has a website which runs a daily competition to win stuff. It has a database of over 250,000 registered users, and each user is sent a daily codeword which they must either enter or click a link in order to register their entry into the drawing. The majority of users have opted to receive an email, but a significant number are now opting to receive the notifications via SMS. Here’s the problem: How do you send a message via two different channels to both groups of users? The logical approach would be to split the users into 2 groups, email recipients and SMS recipients, which would involve running 2 different queries and sending the codeword to each group separately. Using the Command Pattern, which I will introduce you to in this article, you can send the message to both groups of users in a single process.

Messaging Queue using the Command Pattern

The Command Pattern (also sometimes called the Action Pattern or Transaction Pattern) is a design pattern that describes how to encapsulate a request as an object so that you can queue or log clients with different requests. To demonstrate how the Command Pattern works, let’s use the simple example of a message queue. Here’s the definition of the MessageQueue class:
<?php
class MessageQueue
{
    private $queue;

    public function __construct() {
        $this->queue = array();
    }

    public function addMessage(IMessage $msg) {
        $this->queue[] = $msg;
    }

    public function execute() {
        $sendCount = 0;
        foreach ($this->queue as $msg) {
            if ($msg->send()) {
                $sendCount++;
            }
        }
        return $sendCount;
    }
}
The message queue presents two methods – an addMessage() method which adds message objects to the queue, and an execute() method which processes each message in the queue. In this example, the addMessage() method simply appends the messages to the internal array $queue, and the execute() method iterates through the elements in $queue and calls the send()
method for each message object. The Command Pattern queues each request for processing later; the actual mechanism for sending the email or SMS will be implemented in the object’s send() method. MessageQueue doesn’t need to know how to process the request as that will be the responsibility of the requesting object. To ensure the send() method is available, message objects must implement the IMessage interface.
<?php
interface IMessage
{
    public function send();
}
Each message object implements the IMessage interface and provide it’s own implementation of the send() method.
<?php
class DailyAlertEmail implements IMessage
{
...
    public function send() {
        // actual code here to send email
        // ...
        echo "Sending message via emailn";
    }
}

class DailyAlertSMS implements IMessage
{
...
    public function send() {
        // actual code here to send the SMS
        // ...
        echo "Sending message via SMSn";
    }
}
The DailyAlertEmail message implements its send() method for sending the codeword as an email, while the DailyAlertSMS message object implements its send()
method for sending the message as an SMS. Then to send both SMS and email recipients a message you would query the database for their communication preference, instantiate a suitable IMessage object and add it to the message queue, and then call the queue’s execute() method. Incidentally, creating the correct IMessage object for a user would be a good opportunity to use the Factory Method design pattern!
<?php
// create a new queue
$msgQueue = new MessageQueue();

$result = $db->query("SELECT * FROM customers");
while ($customer = $result->fetch(PDO::FETCH_ASSOC)) {
    // factory creates a DailyAlertSMS or DailyAlertEmail object
    // based on the user's preferences
    $msg = MessageFactory::build($customer, $codeword);

    // add the message object to the queue
    $msgQueue->addMessage($msg);
}

// send to all customers now
$msgQueue->execute();
Using the Command Pattern, you can retrieve all customers from the database, instantiate the appropriate IMessage implementations regardless of the customers’ communication preferences, and process them once, instead of querying the database first for all SMS customers and processing them and then repeating the process for email customers. Keep in mind this is a basic example only; In a real world application it would be preferable to batch the SMS and email messages and send them out periodically throughout the day, ideally as a background process. With some minor modifications you can convert this to a “delayed” messaging queue run as a cron task and use the database to monitor the process’ progress.

Summary

As you can see, the Command Pattern is well suited for the following situations:
  • You want to be able to parameterize objects by an action to perform.
  • You need to specify, queue, and execute requests at different times.
  • When a set of changes to data need to be encapsulated as a single action (i.e. a transaction).
In this tutorial I’ve shown you how the Command Pattern can be a useful design pattern for implementing a command queue where requests can be queued for sequential processing, while at the same time decoupling the actual implementation of the execution from the queue itself. Horiyan / Shutterstock

Frequently Asked Questions (FAQs) about the Command Design Pattern

What is the main purpose of the Command Design Pattern?

The Command Design Pattern is primarily used to decouple the sender and receiver of a request. This means that the sender does not need to know the details of the operation being performed or the receiver of the request. Instead, the sender knows how to issue a command, and the command knows how to execute a request. This pattern is particularly useful in scenarios where you want to parameterize objects with operations and queue, specify, and execute requests at different times.

How does the Command Design Pattern work?

The Command Design Pattern works by encapsulating a request as an object, thereby allowing users to parameterize clients with queues, requests, and operations. It involves four components: the Command, the Receiver, the Invoker, and the Client. The Command declares an interface for executing operations, the Receiver knows how to perform the operations, the Invoker holds a command and at some point asks the command to carry out a request by calling its execute method, and the Client creates a ConcreteCommand object and sets its receiver.

What are the benefits of using the Command Design Pattern?

The Command Design Pattern offers several benefits. It decouples the classes that invoke the operation from the object that knows how to execute the operation, it allows you to create a sequence of commands by providing a queue system, and it allows you to control the execution of these commands. Furthermore, it supports undoable operations, as every command is an object with a specific method.

When should I use the Command Design Pattern?

The Command Design Pattern is particularly useful when you need to issue requests to objects without knowing anything about the operation being requested or the receiver of the request. It’s also beneficial when you need to parameterize objects with operations, and when you need to queue, specify, and execute requests at different times.

Can you provide an example of the Command Design Pattern in use?

Sure, a common example of the Command Design Pattern is in the implementation of a menu system in a graphical user interface (GUI). Each action in a menu could be a command. When the user clicks on a menu item, the command associated with that item is executed.

What is the difference between Command and Strategy Design Patterns?

While both patterns encapsulate an algorithm into a separate component, they serve different purposes. The Command Pattern is about separating the responsibilities of issuing a command from executing a command, making it easier to add commands or change the execution of commands. On the other hand, the Strategy Pattern is about defining a family of algorithms, encapsulating each one, and making them interchangeable.

Can the Command Design Pattern be used for undo operations?

Yes, the Command Design Pattern can support undoable operations. To do this, the Command class must maintain the state for reversing its effects and implement an undo method that restores the object to its previous state.

Is the Command Design Pattern applicable in multithreaded programming?

Yes, the Command Design Pattern can be very useful in multithreaded programming. It allows you to encapsulate requests as objects, which can then be executed in separate threads. This can greatly simplify the synchronization of threads.

How does the Command Design Pattern relate to object-oriented design principles?

The Command Design Pattern is a great example of encapsulation – one of the fundamental principles of object-oriented design. It encapsulates a request as an object, thereby letting you parameterize clients with different requests.

Are there any drawbacks to using the Command Design Pattern?

While the Command Design Pattern has many benefits, it’s not without its drawbacks. The main one is that it can lead to an increase in the number of classes, as each command is represented by a separate class. This can make the system more complex and harder to understand.

Ignatius TeoIgnatius Teo
View Author

Ignatius Teo is a freelance PHP programmer and has been developing n-tier web applications since 1998. In his spare time he enjoys dabbling with Ruby, martial arts, and playing Urban Terror.

Intermediate
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week