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;
}
}
}