【JAVA设计模式-第三课】命令模式-让boss给我们加工资
2013-06-02 01:09
465 查看
[b]【JAVA设计模式-第三课】命令模式-让boss给我们加工资[/b]
命令模式
命令模式又称动作模式或事物模式。
将一个请求封装为一个对象,使用户可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
原文:
Command Pattern(Another Name:Action , Transaction)
Encapsulate a request as an object, thereby letting you parameterize clients with different request, queue or log requests, and support undoable operations.
--《Design Patterns》GOF
在设计开发中,很多时候,我们都会遇到这样的情况:一个对象(请求者)请求另一个对象(被请求者)并调用其方法去执行某个动作或者达到某一目的。而这个请求者可能并不需要或者根本无法直接和被请求者打交道,也就是请求者不想或者无法含有被请求者的引用,那么就可以使用命令模式。比如:我们想让boss加工资,但是boss经常出差或者其他什么的(你懂的啊、、),我们根本无法直接联系到他。但是我们的目的是明确的,就是“boss要给我们加工资”。所以就可以把“boss要给我们加工资”作为一个命令。我们只要能将这个“命令”被执行,加工资就现实啦 ^_U。
【X】:命令模式中,当一个对象请求另一个对象并调用其方法时,不和被请求者(接受者)直接通信,而是将这个“请求”封装到一个叫“命令”的对象中,其封装手段是将“请求”封装在“命令”对象的一个方法中。命令模式的核心就是使用命令对象来封装方法调用,即将请求者的请求,"接受者调用方法”封装到命令对象的一个方法中。这样,当一个对象请求另一个对象调用方法来完成某项任务时,只需和命令对象通信就可以了,让命令对象去调用封装了“请求”的那个方法。如下图所示:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_user.jpg)
接下来,我们来分析一下在命令模式的结构中的各个角色。角色包括四种角色,分别为请求者(Invoker)、接收者(Receiver)、命令接口(Command)、具体命令(ConcreteCommand)。
【注释】:
请求者(Invoker):请求者是一个包含了Command接口变量的类的实例。两者的关系为关联关系(类A的属性包括类B或者对象B,则类A与B相关联)。请求者中的Command接口变量可以存放任何具体命令的引用(上转型存储)。请求者负责调用具体命令,让具体命令执行那些封装了“请求”的方法,如execute()方法。
接收者(Receiver):接收者是一个类的实例,负责执行与请求相关的操作。
命令接口(Command):命令是一个接口,规定了用来封装“请求”的若干个方法,比如execute()、undo()等方法。
具体命令(ConcreteCommand) :具体命令是实现了命令接口(Command)的类的实例。具体命令必须实现命令接口中的所有抽象方法,比如execute()方法,使该方法封装一个"请求"。具体命令和命令接口之间的关系就是实现关系。在具体命令中包含了一个接收者变量的类实例,So,两者之间的关系为关联关系。
下图(命令模式的UML类图)
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class.jpg)
下面是类图及具体的代码实现:让boss给我们加工资。
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_1.jpg)
接收者源码
命令接口源码
具体命令源码
请求者源码
命令模式运行源码
运行结果
命令模式中,居然有命令执行的动作,当然也还有命令撤销的动作。即与execute()相对于的方法undo()来撤销execute()方法的执行效果。当然如果execute()方法的执行效果不可撤销(比如:我们退出系统--当退出命令发出,那么就不能撤销该命令了。),那在具体实现(命令)中就不必去实现undo()方法了。
还是针对,以“让boss给我们加工资”为例。我们要求boss给我们加工资,这只是要求,boss们有很多种执行方法,如:同意加工资,不同意加工资,同意之后又反悔撤销了命令,So 我们要在命令接口中增加一些新的方法如undo()。
下面是类图及具体代码实现:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_2.jpg)
为了更好的区分执行和撤销命令动作,我们将在具体接口中新增一个命令集存储器,用于存放各种不同的命令。每个命令都将带有一个命令名字。
类图如下:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_3.jpg)
运行结果:
上一课:【JAVA设计模式-第二课】UML建模简介
命令模式
命令模式又称动作模式或事物模式。
将一个请求封装为一个对象,使用户可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
原文:
Command Pattern(Another Name:Action , Transaction)
Encapsulate a request as an object, thereby letting you parameterize clients with different request, queue or log requests, and support undoable operations.
--《Design Patterns》GOF
在设计开发中,很多时候,我们都会遇到这样的情况:一个对象(请求者)请求另一个对象(被请求者)并调用其方法去执行某个动作或者达到某一目的。而这个请求者可能并不需要或者根本无法直接和被请求者打交道,也就是请求者不想或者无法含有被请求者的引用,那么就可以使用命令模式。比如:我们想让boss加工资,但是boss经常出差或者其他什么的(你懂的啊、、),我们根本无法直接联系到他。但是我们的目的是明确的,就是“boss要给我们加工资”。所以就可以把“boss要给我们加工资”作为一个命令。我们只要能将这个“命令”被执行,加工资就现实啦 ^_U。
【X】:命令模式中,当一个对象请求另一个对象并调用其方法时,不和被请求者(接受者)直接通信,而是将这个“请求”封装到一个叫“命令”的对象中,其封装手段是将“请求”封装在“命令”对象的一个方法中。命令模式的核心就是使用命令对象来封装方法调用,即将请求者的请求,"接受者调用方法”封装到命令对象的一个方法中。这样,当一个对象请求另一个对象调用方法来完成某项任务时,只需和命令对象通信就可以了,让命令对象去调用封装了“请求”的那个方法。如下图所示:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_user.jpg)
接下来,我们来分析一下在命令模式的结构中的各个角色。角色包括四种角色,分别为请求者(Invoker)、接收者(Receiver)、命令接口(Command)、具体命令(ConcreteCommand)。
【注释】:
请求者(Invoker):请求者是一个包含了Command接口变量的类的实例。两者的关系为关联关系(类A的属性包括类B或者对象B,则类A与B相关联)。请求者中的Command接口变量可以存放任何具体命令的引用(上转型存储)。请求者负责调用具体命令,让具体命令执行那些封装了“请求”的方法,如execute()方法。
接收者(Receiver):接收者是一个类的实例,负责执行与请求相关的操作。
命令接口(Command):命令是一个接口,规定了用来封装“请求”的若干个方法,比如execute()、undo()等方法。
具体命令(ConcreteCommand) :具体命令是实现了命令接口(Command)的类的实例。具体命令必须实现命令接口中的所有抽象方法,比如execute()方法,使该方法封装一个"请求"。具体命令和命令接口之间的关系就是实现关系。在具体命令中包含了一个接收者变量的类实例,So,两者之间的关系为关联关系。
下图(命令模式的UML类图)
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class.jpg)
下面是类图及具体的代码实现:让boss给我们加工资。
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_1.jpg)
接收者源码
/** * 接收者 */ public class CompanyBloc { /** * 处理"加薪"命令 */ public void addSalary(){ System.out.println("公司董事会商议决定的,让boss给员工加工资."); } }
命令接口源码
/** * 规定了用于封装"请求"的方法 */ public interface Command { /** * 封装"请求"的方法 */ public abstract void execute(); }
具体命令源码
/** * 具体命令 */ public class ConcreteCommand implements Command{ private CompanyBloc receiver;//接收者 public ConcreteCommand(CompanyBloc receiver){ this.receiver = receiver; } @Override public void execute() { //封装"请求" receiver.addSalary(); //加工资 } }
请求者源码
/** * 请求者 */ public class Employee { private Command command; public Employee(Command command) { this.command = command; } /** * 让具体命令执行execute()方法 */ public void startExecuteCommand() { command.execute(); } }
命令模式运行源码
/** * 使用命令模式 */ public class Application { public static void main(String[] args) { //创建接收者 CompanyBloc receiver = new CompanyBloc(); //创建具体命令并制定接收者 Command command = new ConcreteCommand(receiver); //创建请求者 Employee invoker = new Employee(command); invoker.startExecuteCommand(); } }
运行结果
公司董事会商议决定的,让boss给员工加工资.
命令模式中,居然有命令执行的动作,当然也还有命令撤销的动作。即与execute()相对于的方法undo()来撤销execute()方法的执行效果。当然如果execute()方法的执行效果不可撤销(比如:我们退出系统--当退出命令发出,那么就不能撤销该命令了。),那在具体实现(命令)中就不必去实现undo()方法了。
还是针对,以“让boss给我们加工资”为例。我们要求boss给我们加工资,这只是要求,boss们有很多种执行方法,如:同意加工资,不同意加工资,同意之后又反悔撤销了命令,So 我们要在命令接口中增加一些新的方法如undo()。
下面是类图及具体代码实现:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_2.jpg)
/** * 接收者 */ public class CompanyBloc { /** * 处理"加薪"命令 */ public void addSalary(){ System.out.println("公司董事会商议决定的,让boss给员工加工资."); } /** * 不处理"加薪"命令(取消命令) */ public void cancelSalary(){ System.out.println("公司董事会经过商讨, 做出如下艰难的决定:暂时不让boss给员工加工资."); } }
/** * 规定了用于封装"请求"的方法及撤销命令的方法 */ public interface Command { /** * 封装"请求"的方法 */ public abstract void execute(); /** * 撤销"命令" */ public abstract void undo(); }
/** * 具体命令 */ public class ConcreteCommand implements Command{ private CompanyBloc receiver;//接收者 public ConcreteCommand(CompanyBloc receiver){ this.receiver = receiver; } @Override public void execute() { //封装"请求" receiver.addSalary(); //加工资 } @Override public void undo() { receiver.cancelSalary();//取消加工资 } }
/** * 请求者 */ public class Employee { private Command command; public Employee(Command command) { this.command = command; } /** * 让具体命令执行execute()方法 */ public void startExecuteCommand() { command.execute(); } /** * 让具体命令执行undo()方法 */ public void undoCommand(){ command.undo(); } }
/** * 使用命令模式 */ public class Application { public static void main(String[] args) { //创建接收者 CompanyBloc receiver = new CompanyBloc(); //创建具体命令并制定接收者 Command command = new ConcreteCommand(receiver); //创建请求者 Employee invoker = new Employee(command); invoker.startExecuteCommand(); invoker.undoCommand(); } }
公司董事会商议决定的,让boss给员工加工资. 公司董事会经过商讨, 做出如下艰难的决定:暂时不让boss给员工加工资.
为了更好的区分执行和撤销命令动作,我们将在具体接口中新增一个命令集存储器,用于存放各种不同的命令。每个命令都将带有一个命令名字。
类图如下:
![](http://images.cnblogs.com/cnblogs_com/weijunqiang/485678/o_ml_class_3.jpg)
/** * 接收者 */ public class CompanyBloc { /** * 处理"加薪"命令 */ public void addSalary(String order){ System.out.println("【红】公司董事会商议决定的,同意【"+order+"】方案并择日落实执行."); } /** * 不处理"加薪"命令(取消命令) */ public void cancelSalary(String order){ System.out.println("【黑】公司董事会经过商讨, 做出如下艰难的决定:撤销【"+order+"】"); } }
/** * 规定了用于封装"请求"的方法及撤销命令的方法 */ public interface Command { /** * 封装"请求"的方法 */ public abstract void execute(String orderName); /** * 撤销"命令" */ public abstract void undo(); }
/** * 具体命令 */ public class ConcreteCommand implements Command{ private CompanyBloc receiver;//接收者 private ArrayList<String> orders; public ConcreteCommand(CompanyBloc receiver){ orders = new ArrayList<String>(); this.receiver = receiver; } @Override public void execute(String orderName) { //封装"请求" orders.add(orderName); receiver.addSalary(orderName); //加工资 } @Override public void undo() { if (orders.size() > 0) { int size = orders.size(); String order = orders.get(size - 1); orders.remove(size - 1); receiver.cancelSalary(order);//取消命令 }else{ System.out.println("没有命令需要撤销"); } } }
/** * 请求者 */ public class Employee { private Command command; public Employee(Command command) { this.command = command; } /** * 让具体命令执行execute()方法 */ public void startExecuteCommand(String orderName) { command.execute(orderName); } /** * 让具体命令执行undo()方法 */ public void undoCommand(){ command.undo(); } }
/** * 使用命令模式 */ public class Application { public static void main(String[] args) { //创建接收者 CompanyBloc receiver = new CompanyBloc(); //创建具体命令并制定接收者 Command command = new ConcreteCommand(receiver); //创建请求者 Employee invoker = new Employee(command); String orderName = "要福利、要加薪。"; invoker.startExecuteCommand(orderName); invoker.undoCommand(); orderName = "要福利、去旅游"; invoker.startExecuteCommand(orderName); invoker.undoCommand(); invoker.undoCommand(); } }
运行结果:
【红】公司董事会商议决定的,同意【要福利、要加薪。】方案并择日落实执行. 【黑】公司董事会经过商讨, 做出如下艰难的决定:撤销【要福利、要加薪。】 【红】公司董事会商议决定的,同意【要福利、去旅游】方案并择日落实执行. 【黑】公司董事会经过商讨, 做出如下艰难的决定:撤销【要福利、去旅游】 没有命令需要撤销
上一课:【JAVA设计模式-第二课】UML建模简介
相关文章推荐
- Java设计模式--命令模式
- Java设计模式--命令模式
- 设计模式(Design Pattern) - 行为型模式(Behavioral Pattern) - 命令模式(Command) - Java实现
- 用Java 8 Lambda表达式实现设计模式:命令模式
- java设计模式----命令模式
- Java设计模式(学习整理)---命令模式
- java设计模式-----命令模式
- java软件体系设计模式----命令
- Java设计模式之二十四(命令模式)
- java设计模式,命令模式
- Java设计模式--命令模式
- java设计模式之命令模式Command
- java设计模式之命令模式
- Java设计模式(十八)----命令模式
- java设计模式之命令模式
- JAVA设计模式(15):行为型-命令模式(Command)
- Java设计模式—命令模式
- Java设计模式之命令模式
- java设计模式(一)——适配器、桥接、建造者、职责链、命令
- JAVA设计模式 -- 命令模式