设计模式之命令模式

UML图

设计模式之命令模式

定义:在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象实现二者之间的松耦合

使用场景:请求者跟执行者有紧密的联系,比如遥控操作电视,遥控是请求者,有开、关、选择频道的请求功能。电视是执行者。如果将这些开、关、选择频道的请求直接跟电视进行面向过程的代码编写,这样是不利于代码维护。这个时候将遥控的开、关和选择频道的请求抽象成一个接口类,每个请求实现这个接口类。后续有新请求增加也可以很好的扩展。而对于电视机是请求的执行者,但是不同的电视机可以有不同的实现方式,这里将电视机也抽象成一个接口,具体品牌的电视机实现接口。这样复杂的问题就变成对请求接口跟电视接口的操作。

具体代码实现:

//命令抽象接口  Command.php
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:58
 */
interface Command
{
    public function execute();
}

//开命令具体实现类  CommandOn.php
<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:59
 */
class CommandOn implements Command
{
    public $tv;

    public function __construct(Tv $tv)
    {
        $this->tv = $tv;
    }
    public function execute()
    {
        $this->tv->turnOn();
    }
}

//选择频道命令具体实现类  CommandChange.php
<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:59
 */
class CommandChange implements Command
{
    public $tv;
    public $channel;
    public function __construct(Tv $tv,$channel)
    {
        $this->tv = $tv;
        $this->channel = $channel;
    }
    public function execute()
    {
        $this->tv->changeChannel($this->channel);
    }
}


//关命令具体实现类  CommandOff.php
<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:59
 */
class CommandOff implements Command
{
    public $tv;

    public function __construct(Tv $tv)
    {
        $this->tv = $tv;
    }
    public function execute()
    {
        $this->tv->turnOff();
    }
}

//电视抽象接口 TV.php
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:53
 */
interface TV
{
    public function turnOn();
    public function turnOff();
    public function changeChannel($channel);
}

//创维电视具体实现类  SkyTV.php
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:53
 */
class SkyTV implements TV
{
    public $currentChannel = 0;

    public function turnOn()
    {
        echo "Sky电视开机\n";
    }

    public function turnOff()
    {
        echo "Sky电视关机\n";
    }

    public function changeChannel($channel)
    {
        $this->currentChannel = $channel;
        echo "Sky切换频道".$channel."\n";
    }
}

//TCL电视具体实现类 TclTv.php
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 11:53
 */
class TclTV implements TV
{
    public $currentChannel = 0;

    public function turnOn()
    {
        echo "TCL电视开机\n";
    }

    public function turnOff()
    {
        echo "TCL电视关机\n";
    }

    public function changeChannel($channel)
    {
        $this->currentChannel = $channel;
        echo "TCL切换频道".$channel."\n";
    }
}

//遥控类 Control.php
<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 12:09
 */
class Control
{
    public $tv, $commandOn, $commandOff, $commandChange;

    public function __construct(Command $commandOn, Command $commandOff, Command $commandChange)
    {
        $this->commandOn = $commandOn;
        $this->commandOff = $commandOff;
        $this->commandChange = $commandChange;
    }

    public function turnOn()
    {
        $this->commandOn->execute();
    }

    public function turnOff()
    {
        $this->commandOff->execute();
    }

    public function turnChangel()
    {
        $this->commandChange->execute();
    }

}

//入口文件 Main.php
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 12:04
 */

require_once 'AutoLoader.php';
spl_autoload_register('AutoLoader::AutoLoadClass');
header('Content-type:text/html;charset=utf8');
$skyTv = new SkyTV();
$commandOnSky = new CommandOn($skyTv);
$commandOffSky = new CommandOff($skyTv);
$commandChangeSky = new CommandChange($skyTv,3);
echo "<pre>";
$control = new Control($commandOnSky,$commandOffSky,$commandChangeSky);
$control->turnOn();
$control->turnChangel();
$control->turnOff();

$tclTv = new TclTV();
$commandOn = new CommandOn($tclTv);
$commandOff = new CommandOff($tclTv);
$commandChange = new CommandChange($tclTv,3);
$control = new Control($commandOn,$commandOff,$commandChange);
$control->turnOn();
$control->turnChangel();
$control->turnOff();

//类自动加载 AutoLoader.php
<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/23
 * Time: 10:19
 */
class AutoLoader
{
    public static $classMap = [];
    public static function AutoLoadClass($class)
    {
        if(isset(self::$classMap[$class])) {
            return true;
        }
        $file = $class.'.php';
        if(file_exists($file)) {
            include $file;
            self::$classMap[$class] = $class;
        }
    }

}