B6:命令模式 Command

将一个请求封装成一个对象,从而可以用不同的请求对象对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作.

与状态模式和责任链模式的区别是,命令模式设定一次,统一执行

使用场景:
1.可设计一个队列
2.较容易将命令计入日志
3.允许接收的一方是决定是否否决请求
4.可以实现对请求的撤销和重做
5.加入新的命令类不影响其他的类.
6.把请求一个操作的对象与执行操作的对象分离开.

UML

 

示例代码:

// 命令接口
abstract class  Command
{
    protected $receiver;

    public function __construct(Receiver $receiver)
    {
        $this->receiver = $receiver;
    }
    // 执行命令
    abstract public  function execute($params);
    // 撤销命令
    abstract public function undo();
}

// 具体命令执行者
class UserCommand extends Command
{
    public function execute($params)
    {
        return $this->receiver->command($params);
    }

    public function undo()
    {
        return $this->receiver->undo();
    }
}

// 具体命令执行者2
class EmailCommand extends Command
{
    public function execute($params)
    {
        return $this->receiver->command($params);
    }

    public function undo()
    {
        return $this->receiver->undo();
    }

}

// 命令接受者接口
interface Receiver
{
    public function command($params);
    public function undo();
}

// 命令接受者1
class User implements Receiver
{
    public function command($parms)
    {
        echo '写入:用户增加成功' . $parms;
    }

    public function undo()
    {
        echo '撤销了日志写入';
    }
}


// 命令接受者2
class Email implements Receiver
{
    public function command($parms)
    {
        echo '发送邮件' . $parms;
    }

    public function undo()
    {
        echo '撤销了发送邮件';
    }
}



// 命令请求者
class Invoker
{
    protected $command;

    public function setCommand(Command $command)
    {
        $this->command = $command;
    }

    public function execute($params)
    {
        return $this->command->execute($params);
    }

    public function undo()
    {
        return $this->command->undo();
    }
}

$receiver1 = new User();
$receiver2 = new Email();

$invoker = new Invoker();
$invoker->setCommand(new UserCommand($receiver1));
$invoker->execute('jack');
$invoker->undo();

$invoker->setCommand(new EmailCommand($receiver2));
$invoker->execute('jack');
$invoker->undo();

 

另一个例子:

客户点菜,服务员向厨师发送炒菜命令

/**
 * 厨师,命令接受者与执行者
 * Class Cook
 */
class Cook
{
    public function chaocai()
    {
        echo '开始炒菜了';
    }

    public function zuotang()
    {
        echo '开始做汤';
    }
}

// 命令接口
abstract class Command
{
    protected $cook;

    public function __construct(Cook $cook)
    {
        $this->cook = $cook;
    }
}

// 命令1
class Chaocai extends Command
{
    public function chaocaiCommand()
    {
        $this->cook->chaocai();
    }
}

// 命令2
class Zuotang extends Command
{
    public function zuotangCommand()
    {
        $this->cook->zuotang();
    }
}


// 命令请求者,服务员
class Fuyuwuan
{
    private $chaocai;
    private $zuotang;

    public function __construct(Chaocai $chaocai, Zuotang $zuotang)
    {
        $this->chaocai = $chaocai;
        $this->zuotang = $zuotang;
    }

    public function callChaocai()
    {
        $this->chaocai->chaocaiCommand();
    }

    public function callZuotang()
    {
        $this->zuotang->zuotangCommand();
    }
}

// 客户
$cook = new Cook(); // 新建厨师
// 命令
$chaocai = new Chaocai($cook);
$zuotang = new Zuotang($cook);

$fuwuyuan = new Fuyuwuan($chaocai, $zuotang); // 新建服务员
$fuwuyuan->callChaocai();  // 向服务员点单

  

 

posted @ 2017-11-06 08:12  rorshach  阅读(170)  评论(0编辑  收藏  举报