PHP設計模式之命令列模式(Command)程式碼範例大全(22)

2020-09-19 12:04:40

目的

為了封裝呼叫和解耦。

我們有一個呼叫程式和一個接收器。 這種模式使用「命令列」將方法呼叫委託給接收器並且呈現相同的「執行」方法。 因此,呼叫程式只知道呼叫「執行」去處理使用者端的命令。接收器會從呼叫程式中分離出來。

這個模式的另一面是取消方法的 execute (),也就是 undo () 。命令列也可以通過最小量的複製貼上和依賴組合(不是繼承)被聚合,從而組合成更復雜的命令集。

例子

文字編輯器:所有事件都是可以被解除、堆放,儲存的命令。

Symfony2:SF2 命令可以從 CLI 執行,它的建立只需考慮到命令列模式。

大型 CLI 工具使用子程式來分發不同的任務並將它們封裝在「模型」中,每個模組都可以通過命令列模式實現(例如:vagrant)。

UML圖

★官方PHP高階學習交流社群「點選」管理整理了一些資料,BAT等一線大廠進階知識體系備好(相關學習資料以及筆面試題)以及不限於:分散式架構、高可延伸、高效能、高並行、伺服器效能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell指令碼、Docker、微服務、Nginx等多個知識點高階進階乾貨

程式碼

  • CommandInterface.php

<?php

namespace DesignPatterns\Behavioral\Command;

interface CommandInterface
{
    /**
     * 這是在命令列模式中很重要的方法,
     * 這個接收者會被載入構造器
     */
    public function execute();
}
  • HelloCommand.php

<?php

namespace DesignPatterns\Behavioral\Command;

/**
 * 這個具體命令,在接收器上呼叫 "print" ,
 *  但是外部呼叫者只知道,這個是否可以執行。
 */
class HelloCommand implements CommandInterface
{
    /**
     * @var Receiver
     */
    private $output;

    /**
     * 每個具體的命令都來自於不同的接收者。
     * 這個可以是一個或者多個接收者,但是引數裡必須是可以被執行的命令。
     *
     * @param Receiver $console
     */
    public function __construct(Receiver $console)
    {
        $this->output = $console;
    }

    /**
     * 執行和輸出 "Hello World".
     */
    public function execute()
    {
        // 有時候,這裡沒有接收者,並且這個命令執行所有工作。
        $this->output->write('Hello World');
    }
}
  • Receiver.php

<?php

namespace DesignPatterns\Behavioral\Command;

/**
 * 接收方是特定的服務,有自己的 contract ,只能是具體的範例。
 */
class Receiver
{
    /**
     * @var bool
     */
    private $enableDate = false;

    /**
     * @var string[]
     */
    private $output = [];

    /**
     * @param string $str
     */
    public function write(string $str)
    {
        if ($this->enableDate) {
            $str .= ' ['.date('Y-m-d').']';
        }

        $this->output[] = $str;
    }

    public function getOutput(): string
    {
        return join("\n", $this->output);
    }

    /**
     * 可以顯示訊息的時間
     */
    public function enableDate()
    {
        $this->enableDate = true;
    }

    /**
     * 禁止顯示訊息的時間
     */
    public function disableDate()
    {
        $this->enableDate = false;
    }
}
  • Invoker.php

<?php

namespace DesignPatterns\Behavioral\Command;

/**
 *呼叫者使用這種命令。
 * 比例 : 一個在 SF2 中的應用
 */
class Invoker
{
    /**
     * @var CommandInterface
     */
    private $command;

    /**
     * 在這種呼叫者中,我們發現,訂閱命令也是這種方法
     * 還包括:堆疊、列表、集合等等
     *
     * @param CommandInterface $cmd
     */
    public function setCommand(CommandInterface $cmd)
    {
        $this->command = $cmd;
    }

    /**
     * 執行這個命令;
     * 呼叫者也是用這個命令。
     */
    public function run()
    {
        $this->command->execute();
    }
}

測試

  • Tests/CommandTest.php

<?php

namespace DesignPatterns\Behavioral\Command\Tests;

use DesignPatterns\Behavioral\Command\HelloCommand;
use DesignPatterns\Behavioral\Command\Invoker;
use DesignPatterns\Behavioral\Command\Receiver;
use PHPUnit\Framework\TestCase;

class CommandTest extends TestCase
{
    public function testInvocation()
    {
        $invoker = new Invoker();
        $receiver = new Receiver();

        $invoker->setCommand(new HelloCommand($receiver));
        $invoker->run();
        $this->assertEquals('Hello World', $receiver->getOutput());
    }
}

PHP 網際網路架構師成長之路*「設計模式」終極指南

PHP 網際網路架構師 50K 成長指南+行業問題解決總綱(持續更新)

面試10家公司,收穫9個offer,2020年PHP 面試問題

★如果喜歡我的文章,想與更多資深開發者一起交流學習的話,獲取更多大廠面試相關技術諮詢和指導,歡迎加入我們的群啊,暗號:phpzh(君羊號碼856460874)。

2020年最新PHP進階教學,全系列!

內容不錯的話希望大家支援鼓勵下點個贊/喜歡,歡迎一起來交流;另外如果有什麼問題 建議 想看的內容可以在評論提出