命令模式是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
仔细想一下 这不就是命令行的底层实现嘛?自己之前一直都在使用命令行,而从来没有想过到底是怎么实现的,只需短短键入几个字符就能得到想要的结果。
但是同时 有时候命令太多记不住也很头疼,而且有的时候,如果你不知道某个命令可以做这个事情 那么挫败感就会很强。
英文解释:
encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.
经典的命令模式包括如下4个角色:
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。
角色抽象的一批。
实例
电视机是请求的接收者,遥控器是请求的发送者,遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。显然,电视机遥控器就是一个典型的命令模式应用实例。
代码
抽象命令类:
public interface AbstractCommand{
public void execute();
}
具体的命令类:换台
public class TVChangeCommand implements AbstractCommand{
private Television tv;
public TVChangeCommand(){
tv = new Television();
}
public void execute(){
tv.changeChannel();
}
}
具体的命令类:关机
public class TVCloseCommand implements AbstractCommand{
private Television tv;
public TVCloseCommand(){
tv = new Television();
}
public void execute(){
tv.close();
}
}
具体的命令类:开机
public class TVOpenCommand implements AbstractCommand{
private Television tv;
public TVOpenCommand(){
tv = new Television();
}
public void execute(){
tv.open();
}
}
接收者类
public class Television{
public void open(){
System.out.println("打开电视机!");
}
public void close()
{
System.out.println("关闭电视机!");
}
public void changeChannel()
{
System.out.println("切换电视频道!");
}
}
调用者(Invoker)类
public class Controller {
private AbstractCommand openCommand, closeCommand, changeCommand;
public Controller(AbstractCommand openCommand, AbstractCommand closeCommand, AbstractCommand changeCommand) {
this.openCommand = openCommand;
this.closeCommand = closeCommand;
this.changeCommand = changeCommand;
}
public void open() {
openCommand.execute();
}
public void change() {
changeCommand.execute();
}
public void close() {
closeCommand.execute();
}
}
优缺点
优点
每个命令都被封装起来,对于客户端来说,需要什么功能就去调用相应的命令,而无需知道命令具体是怎么执行的。比如有一组文件操作的命令:新建文件、复制文件、删除文件。如果把这三个操作都封装成一个命令类,客户端只需要知道有这三个命令类即可,至于命令类中封装好的逻辑,客户端则无需知道。
其次,命令模式的扩展性很好,在命令模式中,在接收者类中一般会对操作进行最基本的封装,命令类则通过对这些基本的操作进行二次封装,当增加新命令的时候,对命令类的编写一般不是从零开始的,有大量的接收者类可供调用,也有大量的命令类可供调用,代码的复用性很好。比如,文件的操作中,我们需要增加一个剪切文件的命令,则只需要把复制文件和删除文件这两个命令组合一下就行了,非常方便。
缺点
命令模式的缺点就是命令如果很多,开发起来就要头疼了。特别是很多简单的命令,实现起来就几行代码的事,而使用命令模式的话,不用管命令多简单,都需要写一个命令类来封装。
实例中的实例
TomCat中的命令模式
Tomcat中Connector 也是通过命令模式调用 Container。Connector 作为抽象请求者,HttpConnector 作为具体请求者。HttpProcessor 作为命令。Container 作为命令的抽象接受者,ContainerBase 作为具体的接受者。客户端就是应用服务器 Server 组件了。Server 首先创建命令请求者 HttpConnector 对象,然后创建命令 HttpProcessor 命令对象。再把命令对象交给命令接受者 ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的 Container 执行的。命令可以以队列的方式进来,Container 也可以以不同的方式来处理请求,如 HTTP1.0 协议和 HTTP1.1 的处理方式就会不同。