JAVA设计模式之命令模式

来源:互联网 发布:cf陈子豪刷枪软件 编辑:程序博客网 时间:2024/06/02 06:11

1. 什么是命令模式?

Head First设计模式》书中定义,命令模式将请求封装成对象,从而可以用不同的请求对客户端进行参数化;还可以实现请求队列、请求日志记录、宏命令和请求撤销等操作。


个人理解,命令模式中将请求操作单独封装成对象,可以称之为命令对象,每一个命令包含一个请求接收者和一系列的动作,这样请求者和接收者之间就没有直接耦合,实现了解耦。请求者不用关心请求什么时候执行、怎么执行,也不用知道具体的请求接收者的内部细节,只需要调用具体的命令对象。


Head First设计模式》:在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作。


宏命令是命令的一种简单延伸,允许调用多个命令,即一个命令中包含了多个其他命令,是一组操作命令的集合。

2. 角色

 

(图片来源于网络)

客户端角色(Client:负责创建调用者对象、命令对象和接收者对象,并确定他们之间的调用关系

请求者角色(Invoker:负责调用命令对象执行请求,相关的方法叫行动方法(例如图中call方法)。

接收者角色(Receiver:负责执行和具体实施一个请求。

抽象命令角色(Command:声明了一个所有具体命令共同的抽象接口。具体命令必须实现其中的execute方法。

具体命令角色(ConcreteCommand:拥有共同的接口。其中封装了接收者和一个或一组动作。在请求者和接收者之间起沟通作用,使他们两者解耦。

 

3. 优点

1)将请求执行大动作进行单独封装,使请求动作与执行动作解耦,调用关系更加灵活。

2)请求单独封装成命令过后,能够进行复用,更可以实现请求队列、请求日志记录、请求撤销和宏命令的操作。

3)能够更好的扩展系统功能。当有新的调用关系产生时,只需要增加命令和相关的接收者对象,不会对原有代码结构进行破坏。

4. 缺点

1)将请求执行操作单独封装过后,势必造成类数量的庞大。想要完成某个操作,就必须要了解相应的命令,增加开发者的学习成本。

2)有些简单的命令也必须进行单独的封装。

5. 使用场景

1)系统需要将请求调用者和请求执行者进行解耦,使两者不直接交互。

2)系统需要将请求排队执行、请求日志记录和请求撤销/恢复 的情况。

3)系统需要支持宏命令操作,将多个操作命令组合成一个操作命令。

6. 实例代码

模拟收音机功能,实现播放(play)、暂停(suspend)、倒退(back off)功能。

(1)接收者角色类

/** * 收音机对象,相当于Receiver角色 */public class RadioMachine {/*播放*/public void play(){System.out.println("Radio has played...");}/*暂停*/public void suspend(){System.out.println("Radio has suspended...");}/*倒退*/public void backOff(){System.out.println("Radio has Back off...");}}

(2)抽象命令角色类

/** * 公共抽象命令接口 */public interface Command {public void execute();}
 

(3)具体命令角色类

/** * 播放命令,相当于ConcreteCommand角色 */public class PlayCommand implements Command { RadioMachine radio;public PlayCommand() {radio=new RadioMachine();}@Overridepublic void execute() {radio.play();}} /** * 暂停操作,相当于ConcreteCommand角色 */public class SuspendCommand implements Command { RadioMachine radio;public SuspendCommand() {radio=new RadioMachine();}@Overridepublic void execute() {radio.suspend();}} /** * 倒退操作,相当于ConcreteCommand操作 */public class BackOffCommand implements Command { RadioMachine radio;public BackOffCommand() {radio=new RadioMachine();}@Overridepublic void execute() {radio.backOff();}}

 (4)调用者角色类

/** * 命令请求者 */public class Invoker { Command command;public Invoker() {}/*构造器注入*/public Invoker(Command command) {this.command=command;}/*set方法注入*/public void setCommand(Command command){this.command=command;}/*执行命令*/public void call(){command.execute();}}
 

(5)客户端

/** * 客户端角色 */public class Client { public static void main(String[] args) {Invoker invoker=new Invoker();Command playCommand=new PlayCommand();Command suspendCommand=new SuspendCommand();Command backOffCommand=new BackOffCommand();invoker.setCommand(playCommand);invoker.call();invoker.setCommand(suspendCommand);invoker.call();invoker.setCommand(backOffCommand);invoker.call();}}

(6)测试结果

Radio has played...Radio has suspended...Radio has Back off...

【四川乐山程序员联盟,欢迎大家加群相互交流学习5 7 1 8 1 4 7 4 3】

原创粉丝点击