设计模式之禅之设计模式-命令模式
一:命令模式的定义
--->命令模式是一个高内聚的模式
--->将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
--->命令模式的角色
● Receive接收者角色==>该角色就是干活的角色,命令传递到这里是应该被执行的
● Command命令角色==>需要执行的所有命令都在这里声明
● Invoker调用者角色==>接收到命令,并执行命令。
--->命令模式比较简单,但是在项目中非常频繁地使用,因为它的封装性非常好,把请求方(Invoker)和执行方(Receiver)分开了,扩展性也有很好的保障,通用代码比较简单
二:命令模式的应用
【1】 命令模式的优点
● 类间解耦
-->调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
● 可扩展性
-->Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。
● 命令模式结合其他模式会更优秀
-->命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少Command子类的膨胀问题。
【2】命令模式的缺点
-->命令模式也是有缺点的,请看Command的子类:如果有N个命令,问题就出来了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,这个就需要读者在项目中慎重考虑使用。
三:命令模式的使用场景
-->只要你认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;模拟DOS命令的时候,当然也要采用命令模式;触发-反馈机制的处理等
四:最佳实践
--->这确实简化了很多,每个命令完成单一的职责,而不是根据接收者的不同完成不同的职责。
五:案例
【1】命令抽象类
1 package com.yeepay.sxf.template10; 2 /** 3 * 抽象命令类 4 * @author sxf 5 * 6 */ 7 public abstract class Command { 8 //每个命令类都必须有一个执行命令的方法 9 public abstract void execute(); 10 }
【2】具体命令类1
1 package com.yeepay.sxf.template10; 2 /** 3 * 定义了两个具体的命令类,读者可以在实际应用中扩展该命令类。 4 * 在每个命令类中,通构造函数定义了该命令是针对哪一个接收者发出的,定义一个命令接收的主体。 5 * 调用者非常简单,仅实现命令的传递, 6 * @author sxf 7 * 8 */ 9 public class ConcreteComand1 extends Command{ 10 //接收者 11 private Receiver receiver; 12 13 //构造器 14 public ConcreteComand1(Receiver receiver) { 15 this.receiver=receiver; 16 } 17 //必须实现一个命令 18 @Override 19 public void execute() { 20 this.receiver.doSomething(); 21 } 22 23 }
【3】具体命令类2
1 package com.yeepay.sxf.template10; 2 3 4 /** 5 * 接收命令 6 * @author sxf 7 * 8 */ 9 public class ConcreteComand2 extends Command { 10 //接收者 11 private Receiver receiver; 12 //构造器 13 public ConcreteComand2(Receiver receiver){ 14 this.receiver=receiver; 15 } 16 //必须实现一个命令 17 @Override 18 public void execute() { 19 this.receiver.doSomething(); 20 } 21 22 23 }
【4】接收类(真正的执行者)抽象类
1 package com.yeepay.sxf.template10; 2 /** 3 * 抽象接收者 4 * @author sxf 5 * 很奇怪,为什么Receiver是一个抽象类? 6 * 那是因为接收者可以有多个,有多个就需要定义一个所有特性的抽象集合——抽象的接收者, 7 * 8 */ 9 public abstract class Receiver { 10 //抽象接收者,定义每个接收者都必须完成的业务 11 public abstract void doSomething(); 12 }
【5】(真正的执行者1
1 package com.yeepay.sxf.template10; 2 /** 3 * 接收者1 4 * @author sxf 5 * 6 */ 7 public class ConcreteReciver1 extends Receiver{ 8 9 @Override 10 public void doSomething() { 11 System.out.println("ConcreteReciver1.doSomething()我要登地球"); 12 } 13 14 15 }
【6】真正的执行者2
1 package com.yeepay.sxf.template10; 2 /** 3 * 接收者2 4 * @author sxf 5 * 6 */ 7 public class ConcreteReciver2 extends Receiver { 8 9 @Override 10 public void doSomething() { 11 System.out.println("ConcreteReciver2.doSomething(我要登火星)"); 12 } 13 14 }
【7】调用者
1 package com.yeepay.sxf.template10; 2 /** 3 * 调用者 4 * 调用者就像是一个受气包,不管什么命令,都要接收、执行! 5 * @author sxf 6 * 7 */ 8 public class Invoker { 9 /** 10 * 命令类 11 */ 12 private Command command; 13 /** 14 * 受气包,接收命令 15 * @param command 16 */ 17 public void setCommand(Command command){ 18 this.command=command; 19 } 20 /** 21 * 执行命令 22 */ 23 public void action(){ 24 this.command.execute(); 25 } 26 }
【6】客户端
1 package com.yeepay.sxf.template10; 2 /** 3 * 客户端类 4 * @author sxf 5 * 6 */ 7 public class Client { 8 9 public static void main(String[] args) { 10 //首先声明调用者Invoker 11 Invoker invoker = new Invoker(); 12 //定义一个接收者 13 Receiver receiver=new ConcreteReciver1(); 14 //定义一个发送给接收者的命令。 15 Command command=new ConcreteComand1(receiver); 16 //把命令交给调用者去执行 17 invoker.setCommand(command); 18 //执行命令 19 invoker.action(); 20 21 } 22 }