PHP设计模式之命令模式(Command)详细讲解

标签: php设计模式命令模式   时间:2017-07-27
php命令Command模式是GOF23种模式中的一种,是一种行为模式。这种模式很难理解。本文章向大家介绍了php设计模式之命令模式使用示例和技巧,需要的朋友可以参考一下。

1.什么是php命令模式

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

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

命令模式的四种角色:

1. 接收者(Receiver)负责执行与请求相关的操作

2. 命令接口(Command)封装execute()、undo()等方法

3. 具体命令(ConcreteCommand)实现命令接口中的方法

4. 请求者(Invoker)包含Command接口变量

命令模式的核心思想是,带有某个方法的具体类的实例,作为接口传给使用方。对象的具体类型信息消失。在使用方代码中拿到这个接口后调用这个接口的方法。

具体的执行效果,取决的命令发起人提供的对象是哪一个实现类的。这给了命令发起人完全的控制能力,而使用方代码不关心具体的命令类和方法。同时也使条件判断语句成为多余。

 

2、UML类图

PHP设计模式之命令模式(Command)详细讲解

 

3.php命令模式实现

命令模式的理解,关键有2点:

1. 使用接口。通常命令模式的接口中只有一个方法。 实现类的方法有不同的功能,覆盖接口中的方法。在面向对象编程中,大量使用if…else…,或者switch…case…这样的条件选择语句是“最差实践”。通常这类代码,意味着有重构的余地。命令模式就是干掉条件选择语句的利器。

首先提供一个接口:

public interface Command {
	public void execute();
}

然后提供这个接口的实现类。每一个实现类的方法就是if…else…的一个代码块中的代码。这样,调用方直接把一个具体类的实例传进来即可。如:

Public void test(Command para){
   Para.execute();
}

不需要再判断出现了哪种情况,应该执行哪一段代码。一切的问题都由调用方处理。

如果不使用命令模式,那么如果情况逐步增多,如,从原来的2种,增加到20种,那么方法中的判断就会从1次增加到19次。而使用命令模式,仅仅调用方需要从2个实现类增加到20个实现类即可。上面的test方法根本不需要做任何改变。

2. 主要的用途是,使用参数回调模式。

最主要使用命令模式的方式是使用参数回调模式。命令接口作为方法的参数传递进来。然后,在方法体内回调该接口。

当然,命令模式还可以使用其他方式来使用。不一定非用参数回调模式。

了解完这些之后,可以看一下下面的程序例子。

<?php
	/**
	 * 命令模式
	 *
	 * 将一个请求封装为一个对象从而使你可用不同的请求对客户进行参数化,对请求排除或记录请求日志,以及支持可取消的操作
	 */
	 
	// 命令接口
	interface Command
	{
		public function execute();
	}
	
	class Invoker
	{
		private $_command = array();
		public function setCommand($command) {
	 		$this->_command[] = $command;
		}

		public function executeCommand()
		{
			foreach($this->_command as $command) 
			{
             	$command->execute();
	       	}
	    }

    	public function removeCommand($command)
     	{
        	$key = array_search($command, $this->_command);
			if($key !== false)
			{
            	unset($this->_command[$key]);
	  		}
		}
	}
	
	// 命令接受者
	class Receiver
	{
		private $_name = null;
	
		public function __construct($name) {
	        $this->_name = $name;
	    }
	 
	   	public function action()
		{
	         echo $this->_name." 执行攻击命令(action)<br />";
	    }
	
	    public function action1()
		{
	        echo $this->_name." 执行防御命令(action1)<br/>";
	    }
	}
	
	// 具体的命令
	class ConcreteCommand implements Command
	{
		private $_receiver;
		public function __construct($receiver)
	    {
	  		$this->_receiver = $receiver;
	 	}
	
	    public function execute()
	 	{
	  		$this->_receiver->action();
		}
	}
	
	// 具体命令1
	class ConcreteCommand1 implements Command
	{
	    private $_receiver;
	    public function __construct($receiver)
	    {
	   		$this->_receiver = $receiver;
		}
	
		public function execute()
	 	{
			$this->_receiver->action1();
		}
	}	
	
	// 具体命令2
	class ConcreteCommand2 implements Command
	{
		private $_receiver;
		public function __construct($receiver)
	  	{
	     	$this->_receiver = $receiver;
	 	}
	
		public function execute()
	 	{
			$this->_receiver->action();
	    	$this->_receiver->action1();
		}
	}
	
	
	$objRecevier = new Receiver("小狗");
	$objRecevier1 = new Receiver("刺蛇");
	$objRecevier2 = new Receiver("雷兽");
	
	$objCommand = new ConcreteCommand($objRecevier);
	$objCommand1 = new ConcreteCommand1($objRecevier);
	$objCommand2 = new ConcreteCommand($objRecevier1);
	$objCommand3 = new ConcreteCommand1($objRecevier1);
	$objCommand4 = new ConcreteCommand2($objRecevier2); // 使用 Recevier的两个方法
	
	$objInvoker = new Invoker();
	$objInvoker->setCommand($objCommand);
	$objInvoker->setCommand($objCommand1);
	$objInvoker->executeCommand();
	$objInvoker->removeCommand($objCommand1);
	$objInvoker->executeCommand();
	
	$objInvoker->setCommand($objCommand2);
	$objInvoker->setCommand($objCommand3);
	$objInvoker->setCommand($objCommand4);
	$objInvoker->executeCommand();

?>

程序运行结果:

小狗 执行攻击命令(action)
小狗 执行防御命令(action1)
小狗 执行攻击命令(action)
小狗 执行攻击命令(action)
刺蛇 执行攻击命令(action)
刺蛇 执行防御命令(action1)
雷兽 执行攻击命令(action)
雷兽 执行防御命令(action1)

原文地址:http://www.manongjc.com/article/1862.html