设计模式 命令模式 实例_了解命令设计模式

设计模式 命令模式 实例

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!

您知道今天超过40亿部手机在使用吗? 在澳大利亚,我们的人口约为1100万,手机数量超过2200万,平均每人拥有2部手机!

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?

一家公司有一个网站,每天进行比赛以赢得比赛。 它有一个超过250,000个注册用户的数据库,每个用户每天都会收到一个代码字,他们必须输入或单击一个链接才能将他们的条目注册到图形中。 大多数用户选择接收电子邮件,但是现在有大量用户选择通过SMS接收通知。 问题来了:如何通过两个不同的渠道向两组用户发送消息?

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.

逻辑方法是将用户分为电子邮件收件人和SMS收件人两个组,这将涉及运行2个不同的查询并将代码字分别发送到每个组。 使用本文将向您介绍的命令模式,您可以在单个过程中将消息发送给两组用户。

使用命令模式的消息队列 (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:

命令模式(有时也称为操作模式或事务模式)是一种设计模式,描述了如何将请求封装为对象,以便您可以将具有不同请求的客户端排队或记录在日志中。 为了演示命令模式的工作方式,让我们使用消息队列的简单示例。 这是MessageQueue类的定义:

<?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.

消息队列提供了两种方法-将消息对象添加到队列的addMessage()方法和处理队列中的每个消息的execute()方法。 在此示例中, addMessage()方法仅将消息追加到内部数组$queueexecute()方法遍历$queue的元素,并为每个消息对象调用send()方法。

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.

命令模式将每个请求排队等待以后处理; 发送电子邮件或SMS的实际机制将在对象的send()方法中实现。 MessageQueue不需要知道如何处理请求,因为这将是请求对象的责任。 为了确保send()方法可用,消息对象必须实现IMessage接口。

<?php
interface IMessage
{
    public function send();
}

Each message object implements the IMessage interface and provide it’s own implementation of the send() method.

每个消息对象都实现IMessage接口,并提供其自己的send()方法实现。

<?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.

DailyAlertEmail消息实现其send()方法以将代码字作为电子邮件发送,而DailyAlertSMS消息对象实现其send()方法以将消息作为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!

然后,要向SMS和电子邮件接收者发送消息,您可以查询数据库的通信首选项,实例化一个合适的IMessage对象,并将其添加到消息队列中,然后调用队列的execute()方法。 顺便说一句,为用户创建正确的IMessage对象将是使用Factory Method设计模式的好机会!

<?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.

使用命令模式,您可以从数据库中检索所有客户,实例化适当的IMessage实现,而与客户的通信首选项无关,并对其进行一次处理,而不是先为所有SMS客户查询数据库并进行处理,然后重复该过程对于电子邮件客户。

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.

请记住,这只是一个基本示例; 在现实世界的应用程序中,最好将SMS和电子邮件分批处理,并在一整天中定期将其发送出去,最好是作为后台进程。 通过一些小的修改,您可以将其转换为作为cron任务运行的“延迟”消息队列,并使用数据库监视进程的进度。

摘要 (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

霍里扬 / Shutterstock

翻译自: https://www.sitepoint.com/understanding-the-command-design-pattern/

设计模式 命令模式 实例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值