PHP - - By Ignatius Teo

Understanding the Command Design Pattern

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

Sponsors