命令模式(Command)
@@@模式定义:
将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,
对请求排队或记录请求日志,以及支持可撤销的操作。
@@@练习示例:
电脑开机
@@@示例代码:
\pattern\MainBoardApi.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 主板的接口 */ public interface MainBoardApi { /** * 主板具有能开机的功能 */ public void open(); /** * 主板具有实现重启的功能 */ public void reset(); }
\pattern\GigaMainBoard.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 技嘉主板类,开机命令的真正实现者,在Command模式中充当Receiver */ public class GigaMainBoard implements MainBoardApi { /** * 真正的开机命令的实现 */ public void open() { System.out.println("技嘉主板现在正在开机,请等候"); System.out.println("接通电源……"); System.out.println("设备检查……"); System.out.println("装载系统……"); System.out.println("机器正常运转起来……"); System.out.println("机器已经正常打开,请操作"); } /** * 真正的重新启动机器命令的实现 */ public void reset() { System.out.println("技嘉主板现在正在重启机器,请等候"); System.out.println("机器已经正常打开,请操作"); } }
\pattern\Command.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 命令接口,申明执行的操作 */ public interface Command { /** * 执行命令对应的操作 */ public void execute(); }
\pattern\OpenCommand.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 开机命令的实现,实现Command接口 * 持有开机命令的真正实现,通过调用接收者的方法来实现命令 */ public class OpenCommand implements Command { /** * 持有真正实现命令的接收者——主板对象 */ private MainBoardApi mainBoard = null; /** * 构造方法,传入主板对象 * @param mainBoard 主板对象 */ public OpenCommand(MainBoardApi mainBoard) { this.mainBoard = mainBoard; } @Override public void execute() { // 对于命令对象,根本不知道如何开机,会转调主板对象 // 让主板去完成开机的功能 this.mainBoard.open(); } }
\pattern\ResetCommand.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 重启机器命令的实现,实现Command接口 * 持有重启机器命令的真正实现,通过调用接收者的方法来实现命令 */ public class ResetCommand implements Command { /** * 持有真正实现命令的接收者——主板对象 */ private MainBoardApi mainBoard = null; /** * 构造方法,传入主板对象 * @param mainBoard 主板对象 */ public ResetCommand(MainBoardApi mainBoard) { this.mainBoard = mainBoard; } @Override public void execute() { // 对于命令对象,根本不知道如何开机,会转调主板对象 // 让主板去完成重启机器的功能 this.mainBoard.reset(); } }
\pattern\Box.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 机箱对象,本身有按钮,持有按钮对应的命令对象 */ public class Box { /** * 开机命令对象 */ private Command openCommand; /** * 设置开机命令对象 * @param command 开机命令对象 */ public void setOpenCommand(Command command) { this.openCommand = command; } /** * 提供给客户使用,接收并响应用户请求,相当于开机按钮被按下触发的方法 */ public void openButtonPressed() { // 按下按钮,执行命令 openCommand.execute(); } private Command resetCommand; /** * 设置重启机器命令对象 * @param command */ public void setResetCommand(Command command) { this.resetCommand = command; } /** * 提供给客户使用,接收并响应用户请求,相当于重启按钮被按下触发的方法 */ public void resetButtonPressed() { // 按下按钮,执行命令 resetCommand.execute(); } }
\pattern\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; public class Client { public static void main(String[] args) { // 1: 把命令和真正的实现组合起来,相当于在组装机器 // 把机箱上按钮的连接线插接到主板上 MainBoardApi mainBoard = new GigaMainBoard(); // 创建开机命令 OpenCommand openCommand = new OpenCommand(mainBoard); // 创建重启命令 ResetCommand resetCommand = new ResetCommand(mainBoard); // 2: 为机箱上的按钮设置对应的命令,让按钮知道该干什么 Box box = new Box(); // 先正确配置,就是开机按钮对开机命令,重启按钮对重启命令 box.setOpenCommand(openCommand); box.setResetCommand(resetCommand); // 3: 然后模拟按下机箱上的按钮 System.out.println("正确配置下------------------>"); System.out.println(">>>按下开机按钮:>>>"); box.openButtonPressed(); System.out.println(">>>按下重启按钮:>>>"); box.resetButtonPressed(); // 然后来错误配置一回,反正是进行参数化配置 // 就是开机按钮对重启命令,重启按钮对开机命令 box.setOpenCommand(resetCommand); box.setResetCommand(openCommand); System.out.println("错误配置下------------------>"); System.out.println(">>>按下开机按钮:>>>"); box.openButtonPressed(); System.out.println(">>>按下重启按钮:>>>"); box.resetButtonPressed(); } }
@@@模式的实现:
1) 命令模式的关键之处就是把请求封装成为对象,也就是命令对象,并定义了一个统一操作的接口;
2) 可实现成参数化的命令模式;
3) 可实现(补偿式/反操作式)可撤销的操作;
4) 可实现宏命令(命令集);
5) 可实现队列请求;
6) 可实现日志请求;
@@@模式的优点:
1) 更松散的耦合;
2) 更动态的控制;
3) 很自然的复合命令;
4) 更好地扩展性;
@@@模式的缺点:
NA
@@@模式的本质:
封装请求
@@@模式体现的设计原则:
NA