• 【命令模式】设计模式之命令模式【原创】


    摘要:主要是参考列旭松、陈文著的《PHP核心技术与最佳实践》的2.1节。

    1.1 简介

    命令模式:
    将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化。对请求排队或记录请求日志,以及支持撤销的操作。

    命令模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。

    1.2 命令模式的角色

    命令模式的五种角色:
    • 接收者(Receiver):真正执行命令的对象,负责执行与请求相关的操作
    • 命令接口(Command):定义命令的接口,封装execute()、undo()等方法
    • 具体命令(ConcreteCommand):命令接口实现对象,实现命令接口中的方法,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
    • 请求者(Invoker):要求命令对象执行请求,通常会持有命令对象,包含Command接口变量
    • 客户端(Client):创建具体的命令对象

    如下是命令模式的类图:

    1.3 命令模式的优缺点

    命令模式的优点:
    • 降低系统的耦合度
    • 新的命令可以很容易地加入到系统中
    • 可以比较容易地设计一个组合命令
    • 调用同一方法实现不同的功能

    命令模式的缺点:
    使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

    1.4 具体例子

    举个具体的例子,去餐馆吃饭,餐馆存在顾客、服务员、厨师三个角色,作为顾客,只需要列出菜单,传给服务员,服务员通知厨师去实现,而作为服务员,只需要调用准备饭菜这个方法(对厨师通知饭菜),厨师听到要炒菜的请求,立刻去炒。

    先来实现命令模式的接收者(在这里即厨师):
    2_6_RestaurantCook.php:
    1
    <?php
    2
    /**
    3
     * 厨师类,实现炒和煮的方法,即命令模式的命令接受者与执行者
    4
     */
    5
    6
    /**
    7
     * 厨师类,命令接受者与执行者
    8
     * Class Cook
    9
     */
    10
    class Cook
    11
    {
    12
        public function meal()
    13
        {
    14
            echo '番茄炒鸡蛋' . PHP_EOL;
    15
        }
    16
    17
        public function drink()
    18
        {
    19
            echo '紫菜蛋花汤' . PHP_EOL;
    20
        }
    21
    22
        public function ok()
    23
        {
    24
            echo '完毕' . PHP_EOL;
    25
        }
    26
    }
    27

    然后实现命令接口:
    2_6_RestaurantCommand.php:
    <?php
    /**
     * 命令接口
     */
    
    /**
     * 命令接口
     * Interface Command
     */
    interface Command
    {
        public function execute();
    }


    接着实现具体的命令(在这里即服务员向厨师通知的具体命令):
    2_6_RestaurantMealCommand.php:
    1
    <?php
    2
    /**
    3
     * 服务员通知厨师做炒菜的命令类,命令模式中的具体命令之一
    4
     */
    5
    6
    require_once 'Command.php';
    7
    8
    /**
    9
     * 服务员通知厨师做炒菜的命令类
    10
     * Class MealCommand
    11
     * @package Cook
    12
     */
    13
    class MealCommand implements Command
    14
    {
    15
        private $cook;
    16
    17
        /**
    18
         * 绑定命令接收者(厨师)
    19
         * MealCommand constructor.
    20
         * @param cook $cook
    21
         */
    22
        public function __construct(cook $cook)
    23
        {
    24
            $this->cook = $cook;
    25
        }
    26
    27
        /**
    28
         * 让厨师执行炒菜的命令
    29
         */
    30
        public function execute()
    31
        {
    32
            $this->cook->meal();
    33
        }
    34
    }
    以及还有煮汤的具体命令:
    2_6_RestaurantDrinkCommand.php:
    <?php
    /**
     * 服务员通知厨师煮汤的命令类,命令模式中的具体命令之一
     */
    
    /**
     * 服务员通知厨师煮汤的命令类
     * Class DrinkCommand
     * @package Cook
     */
    class DrinkCommand implements Command
    {
        private $cook;
    
        /**
         * 绑定命令接收者(厨师)
         * MealCommand constructor.
         * @param cook $cook
         */
        public function __construct(cook $cook)
        {
            $this->cook = $cook;
        }
    
        /**
         * 让厨师执行煮汤的命令
         */
        public function execute()
        {
            $this->cook->drink();
        }
    }


    最后是命令模式的请求者(在这里即顾客点菜):
    2_6_RestaurantCookControl.php:
    1
    <?php
    2
    /**
    3
     * 顾客点菜类,命令模式的请求者
    4
     */
    5
    6
    class CookControl
    7
    {
    8
        private $mealcommand;
    9
        private $drinkcommand;
    10
    11
        /**
    12
         * 将命令发送者绑定到命令接收器上面来
    13
         * @param Command $mealcommand
    14
         * @param Command $drinkcommand
    15
         */
    16
        public function AddCommand(Command $mealcommand, Command $drinkcommand)
    17
        {
    18
            $this->mealcommand = $mealcommand;
    19
            $this->drinkcommand = $drinkcommand;
    20
        }
    21
    22
        public function callmeal()
    23
        {
    24
            $this->mealcommand->execute();
    25
        }
    26
    27
        public function calldrink()
    28
        {
    29
            $this->drinkcommand->execute();
    30
        }
    31
    32
    }

    命令模式的代码已经完成,可以写个代码测试一下,即模拟一下顾客点菜(客户端):
    2_6_Restaurantexample.php:
    <?php
    /**
     * 模拟顾客点了一个菜和一个汤
     */
    
    // 采用自动载入类,不用手动去require所需的类文件
    spl_autoload_register('autoload');
    
    function autoload($class)
    {
        require __DIR__.'/'.$class.'.php';
    }
    
    $control = new CookControl();
    $cook = new Cook();
    $mealcommand = new MealCommand($cook);
    $drinkcommand = new DrinkCommand($cook);
    $control->AddCommand($mealcommand, $drinkcommand);
    $control->callmeal();
    $control->calldrink();

    运行:
    番茄炒鸡蛋
    紫菜蛋花汤





  • 相关阅读:
    99乘法表-利用数组
    100以内素数
    99乘法表
    第6周小组作业:软件测试和评估
    第4周小组作业:WordCount优化
    第2周个人作业:WordCount
    博客阅读和思考
    第一个C#窗体应用程序开发总结-----单号单面法调整单操作程序
    实验十——一维数组的定义及引用
    实验九——基本数据类型存储及应用总结
  • 原文地址:https://www.cnblogs.com/linewman/p/9918109.html
Copyright © 2020-2023  润新知