在程序设计中,经常设计到一个对象需要请求另外一个对象调用其方法达到某种目的,如果请求这不希望或不直接和被请求者打交道,既请求者不包含被请求者的引用,那么就可以使用命令模式。例如在军队中,指挥官请求三连偷袭敌人,但是指挥官不希望或无法直接与三连取得联系,那么可以将该请求形成一个命令,该命令的核心是让三连偷袭敌人。只要能让该命令被执行,就会实现偷袭敌人的目的。
命令模式是关于怎样处理一个对象请求到另一个对象调用其方法完成某项任务的一种成熟的模式,这里称提出请求的对象为请求者,被请求的对象为接收者。在命令模式中,当一个对象请求另一个对象其调用方法时,不和被请求的对象直接打交道,而是把这这种请求封装到一个命令的对象中,起封装的手段是将请求封装在命令对象的一个方法中。命令模式的核心就是使用命令对象来封装方法调用。既请求者的请求,接受者调用方法。
结构:
命令者模式包括四种角色
接收者:接受者是一个类的实例,该实例负责执行与请求相关的操作
命令:命令是一个接口,规定了用来封装请求的若干个方法。
具体命令:具体命令是实现命令接口的类的实例,具体命令必须实现命令接口中的方法。
请求者:请求者是一个包含”命令接口“变量的类的实例。请求者中的”命令“接口的变量可以存放任何具体命令的引用,请求者负责调用具体命令,让具体命令执行那些封装了请求的方法
代码实例:
接受者
- /**
- * 接受者:具体执行命令的人
- * @author hnylchf
- *
- */
- public class Receiver {
- public void sendMessage(){
- System.out.println("保证完成任务");
- }
- }
命令
- package org.zhy.command;
- /**
- * 命令,封装请求的方法
- * @author hnylchf
- *
- */
- public interface Command {
- public void exceute();
- }
请求者
- package org.zhy.command;
- /**
- * 请求者
- *
- * @author hnylchf
- *
- */
- public class Invoker {
- Command command;
- public void startExceuteCommand(Command command) {
- this.command = command;
- command.exceute();
- }
- }
具体命令
- package org.zhy.command;
- /**
- * 具体命令
- *
- * @author hnylchf
- *
- */
- public class ConcreteCommand {
- Receiver receiver;
- public ConcreteCommand(Receiver receiver) {
- this.receiver = receiver;
- }
- public void execute() {
- receiver.sendMessage();
- }
- }
演示:
- package org.zhy.command;
- public class Appliction {
- public static void main(String[] args) {
- Receiver receiver = new Receiver(); //执行者
- Command command = new ConcreteCommand(receiver); //命令和具体命令
- Invoker invoker = new Invoker(); //请求者
- invoker.startExceuteCommand(command); //请求者下达命令
- }
- }
命令接口的撤销方法
命令接口中规定了用来封装请求的方法比如上例的execute方法,命令接口中还可以提供用来封装撤销请求的方法。既撤销方法的执行能撤销execute方法的执行效果。如果execute方法的执行效果不可撤销,那么具体命令就不必实现撤销方法。
以下示例一个关于撤销方法的demo
命令:
- package org.zhy.commandundo;
- public interface Command {
- public void execute(String name);
- public void undo();
- }
具体命令:
- package org.zhy.commandundo;
- import java.util.ArrayList;
- public class ConcreteCommand implements Command {
- ArrayList<String> dirNameList;
- MakeDir dir;
- public ConcreteCommand(MakeDir dir) {
- dirNameList = new ArrayList<String>();
- this.dir = dir;
- }
- @Override
- public void execute(String name) {
- dir.createDir(name);
- dirNameList.add(name); //记录添加到list中
- }
- @Override
- public void undo() {
- if (dirNameList != null && dirNameList.size() > 0) {
- String str = dirNameList.get(dirNameList.size() - 1);
- dir.deleteDir(str);
- dirNameList.remove(dirNameList.size() - 1);
- } else {
- System.out.println("没有需要操作的记录");
- }
- }
- }
执行者
- package org.zhy.commandundo;
- import java.io.File;
- public class MakeDir {
- public void createDir(String name) {
- File file = new File(name);
- file.mkdir();
- }
- public void deleteDir(String name) {
- File file = new File(name);
- file.delete();
- }
- }
请求者
- package org.zhy.commandundo;
- public class RequestMakedir {
- Command command;
- public RequestMakedir(Command command) {
- this.command = command;
- }
- public void startExecuteCommand(String name) {
- command.execute(name);
- }
- public void undoExecuteCommand() {
- command.undo();
- }
- }
演示
- package org.zhy.commandundo;
- public class Appliction {
- public static void main(String[] args) {
- MakeDir dir = new MakeDir();
- Command command = new ConcreteCommand(dir);
- RequestMakedir requestMakedir = new RequestMakedir(command);
- requestMakedir.startExecuteCommand("jiafei");
- requestMakedir.startExecuteCommand("jiafei2");
- requestMakedir.startExecuteCommand("jiafei3");
- requestMakedir.undoExecuteCommand();
- }
- }
宏命令:
宏命令也是一个具体的命令,只不过他包含了其他命令的引用。当一个宏命令执行其execute方法时,将导致所引用的其他命令执行,因此执行一个宏命令相当于执行了多具体命令。
请求者输入英文字母或1-n之间的偶数可以请求既输出英文字母表,又输出1-n之间的偶数。
首先设计两个接收者,一个是输出英文字母表,一个是输出1-n之间的偶数
接收者1:打印英文字母
- package org.zhy.commandmacro;
- public class PrintLetter {
- public void printEnglish() {
- for (char c = 'a'; c < 'z'; c++) {
- System.out.print(" " + c);
- }
- }
- }
接受者2:打印偶数
- package org.zhy.commandmacro;
- public class PrintNumber {
- int n;
- public PrintNumber(int n) {
- this.n = n;
- }
- public void printEventNumber() {
- for (int i = 0; i <= n; i++) {
- if (i % 2 == 0) {
- System.out.print(" " + i);
- }
- }
- }
- }
命令:
- package org.zhy.commandmacro;
- public interface Command {
- public void execute();
- }
命令1:处理打印字母
- package org.zhy.commandmacro;
- public class PrintEnglishCommand implements Command {
- PrintLetter letter;
- public PrintEnglishCommand(PrintLetter letter) {
- this.letter = letter;
- }
- @Override
- public void execute() {
- letter.printEnglish();
- }
- }
命令2:处理打印偶数
- package org.zhy.commandmacro;
- public class PrintNumberCommand implements Command {
- PrintNumber number;
- public PrintNumberCommand(PrintNumber number) {
- this.number = number;
- }
- @Override
- public void execute() {
- number.printEventNumber();
- }
- }
命令3:宏命令处理一批命令(打印字母和打印偶数)
- package org.zhy.commandmacro;
- import java.util.ArrayList;
- public class MacroCommand implements Command {
- ArrayList<Command> commandList;
- public MacroCommand(ArrayList<Command> commandList) {
- this.commandList = commandList;
- }
- @Override
- public void execute() {
- for (Command command : commandList) {
- command.execute();
- }
- }
- }
请求者
- package org.zhy.commandmacro;
- public class RequestPerson {
- Command command;
- public Command getCommand() {
- return command;
- }
- public void setCommand(Command command) {
- this.command = command;
- }
- public void startExecuteCommand() {
- command.execute();
- }
- }
演示
- package org.zhy.commandmacro;
- import java.util.ArrayList;
- public class Appliction {
- public static void main(String[] args) {
- ArrayList<Command> commandList = new ArrayList<Command>();
- RequestPerson person = new RequestPerson();
- Command englishCommand = new PrintEnglishCommand(new PrintLetter());
- Command numberCommand = new PrintNumberCommand(new PrintNumber(10));
- commandList.add(englishCommand);
- commandList.add(numberCommand);
- Command macroCommand = new MacroCommand(commandList);
- person.setCommand(macroCommand);
- person.startExecuteCommand();
- }
- }
命令者模式的优点
1、在命令者模式中,请求者不直接与接受者互交,既请求者不包含接受者的引用,因此彻底消除了彼此之间的耦合。
2、命令者模式满足了软件的“开-闭原则”。如果增加新的具体命令和该命令的接受者,不必修改调用者的代码,调用者就可以直接使用新的命令对象。反之如果增加新的调用者,不必修改现有的具体命令和接受者。新增加的调用者就可以使用已有的具体命令
3、由于请求者的请求被封装到了具体命令中,那么就可以将具体命令保存到持久化媒介中,在需要的时候重新执行这个具体命令。因此使用命令者模式可以记录日志
4、使用命令者模式可以对请求者的请求进行排队,每个请求者各自对应一个具体命令,因此可以按一定的顺序执行这些命令。
适用命令者模式的场景
1、程序需要在不同的时刻指定,排列和执行请求
2、程序需要提供撤销操作
3、程序需要支持宏操作
相关推荐
JAVA-设计模式-行为型模式-命令模式
设计模式--命令模式java例子
java常用设计模式-命令模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段...
java 设计模式 单例模式 工厂模式 命令模式 模式解析 各种模式的最全面的解析 最朴实的话语
1.3.2 命令模式 40 1.3.3 解释器模式 43 1.3.4 迭代器模式 45 1.3.5 中介者模式 49 1.3.6 备忘录模式 52 1.3.7 观察者模式 54 1.3.8 状态模式 58 1.3.9 策略模式 61 1.3.10 模板方法 63 1.3.11 访问者模式 65
该PPT用于公司内部分享设计模式6---命令模式之用,言简意赅,形象生动.故此分享,希望大家一起学习
计算机后端-Java-图解java设计模式104 命令模式(4)-Jdbc.avi
72-Java设计模式 命令模式1
目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 1.3 我单纯,所以我快乐 1.4 最佳实践 ...附录:23个设计模式
18命令模式:定义命令接口、定义接受者、实现具体命令接口命令模式:定义命令接口、定义接受者、实现具体命令接口 设计模式(JAVA语言实现)--20种设计模式附带源码PPT模板全文共22页,当前为第19页。 19备忘录模式...
计算机后端-Java-图解java设计模式102 命令模式(2.avi
计算机后端-Java-图解java设计模式103 命令模式(3.avi
计算机后端-Java-图解java设计模式101 命令模式(1).avi
计算机后端-Java-图解java设计模式105 命令模式(5).avi
20020_RocketMQ_管理员命令 JAVA-ACE-架构师系列视频教程RocketMQ订单实战下目录介绍: 101_rocketmq_实战项目介绍(免费观看) 202_rocketMQ实战项目设计(一) 303_rocketMQ实战项目设计(二) 404_rocketMQ实战-...
本系统基于六种设计模式,运用到的设计模式有备忘录模式,简单工厂模式,迭代器模式,状态模式,模版方法模式,单例模式。 具体实现过程、UML类图以及实现效果详见如下项目说明地址: ... 该系统为绘图系统,该系统通过...
设计模式主要分为三大类: 1.创建型模式:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。 2.结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。 4.行为型模式:...
这是JAVA设计模式中属于行为模式的部分,包括Template(模板模式)、Chain of Responsibility(责任链模式)、Memento(纪念品模式)、Mediator(中介模式)、Strategy(策略模式)、State 、Observer(观察者模式)、Visitor...
命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State...