PHP设计模式:命令Command模式

使条件判断语句成为多余
服务器君一共花费了320.171 ms进行了6次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

命令Command模式是GOF23种模式中的一种,是一种行为模式。这种模式很难理解。《设计模式》一书中对它语焉不详。而网上的一些文章对其的解释也是错误的。实际上,命令模式并不是那么神秘。

命令模式的理解,关键有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)

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

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

简单吗?命令模式其实就是这么简单。

其实,GOF的23个设计模式中,好几个模式使用了相同的技巧来实现。GOF对模式的划分,是根据目的来的,而不是技巧来的。因此,Command模式和策略模式等其实使用的技法是一样的。 上回和一个同事聊技术。他的背景是Windows C++和Windows驱动开发。 他说,他不知道什么设计模式。他觉得最有用的就是回调函数。Command模式也是使用回调函数。java没有函数指针,java中一切都是类和类的实例。因此,就需要使用一个只有一个函数的接口,它的实例表示函数指针。其实是一回事。

设计模式是比较低层次的设计思想。在更高层次上,还有更加宏观的一些设计技巧。 Bob大叔的一本书不错,忘记名字了。 《Unix编程艺术》也不错,都是讲更高层次上的设计的。

延伸阅读

此文章所在专题列表如下:

  1. PHP设计模式:命令Command模式
  2. PHP设计模式:模板Template模式
  3. PHP设计模式:代理Proxy模式
  4. PHP设计模式:状态State模式
  5. PHP设计模式:享元FlyWeight模式

本文地址:http://www.nowamagic.net/librarys/veda/detail/1570,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/1570

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《编译原理(第2版)》 Alfred V. Aho (作者), Monica S.Lam (作者), 赵建华 (译者), 郑滔 (译者), 戴新宇 (译者)

《编译原理(第2版)》全面、深入地探讨了编译器设计方面的重要主题,包括词法分析、语法分析、语法制导定义和语法制导翻译、运行时刻环境、目标代码生成、代码优化技术、并行性检测以及过程间分析技术,并在相关章节中给出大量的实例。与上一版相比,《编译原理(第2版)》进行了全面的修订,涵盖了编译器开发方面的最新进展。每章中都提供了大量的系统及参考文献。《编译原理(第2版)》是编译原理课程方面的经典教材,内容丰富,适合作为高等院校计算机及相关专业本科生及研究生的编译原理课程的教材,也是广大技术人员的极佳参考读物。

更多计算机宝库...