将“请求”封装成对象,以便使用不一样的请求、队列或者日志来参数化其余对象。命令模式也支持可撤销的操做。 java
调用者与实现者一般是一种紧耦合的关系,但某些场合,好比须要对行为进行记录、撤销或重作、事务等处理时,这种没法抵御变化的紧耦合的设计就不太合适。 我一般这么理解命令模式,某些业务场景,一族对象会有一组命令,以命令的角度为主定义命令对象(有执行和撤回两种操做),而后把执行的过程委托给对象。this
什么是一族对象?举个例子,就是奔驰汽车、宝马汽车、奥迪汽车等。spa
什么是一组命令?举个例子,就是远程控制汽车时的开门命令、开空调命令、开天窗命令等。线程
这种状况就可使用命令模式。使用命令模式有下降耦合、可扩展、可读性高、使用方便(可撤回)等等的好处。设计
具体咱们来看一下,如何用Java代码实现命令模式。日志
仍是以上面的需求为例子,使用命令模式对上面的业务进行实现,下面是类图和代码:code
代码以下:对象
// 车辆抽象类 public abstract class Vehicle { abstract void openDoor(); abstract void openWindow(); } public class Audi extends Vehicle { void openDoor() { System.out.println("奥迪:开门。"); } void openWindow() { System.out.println("奥迪:开窗。"); } } public class Benz extends Vehicle { void openDoor() { System.out.println("奔驰:开门。"); } void openWindow() { System.out.println("奔驰:开窗。"); } } // 命令模式接口 public interface Command { void execute(); } // 开门命令 public class OpenDoorCommand implements Command { private Vehicle vehicle; public OpenDoorCommand(Vehicle vehicle) { this.vehicle = vehicle; } public void execute() { vehicle.openDoor(); } } // 开窗命令 public class OpenWindowCommand implements Command { private Vehicle vehicle; public OpenWindowCommand(Vehicle vehicle) { this.vehicle = vehicle; } public void execute() { vehicle.openWindow(); } } public class Client { public static void main(String[] args) { // 建立开门命令 Command openDoorCommand = new OpenDoorCommand(new Benz()); // 建立开窗命令 Command openWindowCommand = new OpenWindowCommand(new Audi()); // 执行2个命令 openDoorCommand.execute(); openWindowCommand.execute(); } } //输出: //奔驰:开门。 //奥迪:开窗。
使用命令的模式的好处以下:blog
功能足够简单。若是功能自己比较简单,则不建议引入命令模式,它会带来更多的复杂性,以及更高的开发成本。接口
命令的意义不清晰或常常变化时,则不太适合使用命令模式。
通常来讲,尽可能设计傻瓜式命令,它只懂得调用一个接收者的一个行为(单一职责)。
如何实现撤销命令,是一直值得讨论的问题,面相扩展性来讲,能够遵循一个设计方式:
不要只是记录最后一个命令,而使用一个堆栈(后进先出)记录操做过的每个命令。而后,无论何时执行撤销,你均可以从堆栈中取出最上层的命令,而后执行undo()方法来撤销它。
最后说一些其余的,命令模式还能够有更多的用途,好比使用在队列请求和日志请求。
想象一下,有一个工做队列(先进先出),你在某一端添加命令,而后另外一端则是线程,线程从队列中取出一个命令,而后调用它的execute()方法,等待这个调用完成,而后丢弃该命令,执行下一个……
在想象一下,某些应用须要咱们将全部的动做都记录在日志中,并能在系统死机后,从新调用这些动做恢复到以前的状态。咱们能够在执行命令的时候,将历史记录存储在磁盘中。一旦系统死机重启后,咱们就能够将命令对象读取出来从新执行execute()方法。
以上就是我对命令模式的一些理解,有不足之处请你们指出,谢谢。