JAVA设计模式之命令模式

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();
}
@Override
public void execute() {
radio.play();
}
}
 
/**
 * 暂停操作,相当于ConcreteCommand角色
 */
public class SuspendCommand implements Command {
 
RadioMachine radio;
public SuspendCommand() {
radio=new RadioMachine();
}
@Override
public void execute() {
radio.suspend();
}
}
 
/**
 * 倒退操作,相当于ConcreteCommand操作
 */
public class BackOffCommand implements Command {
 
RadioMachine radio;
public BackOffCommand() {
radio=new RadioMachine();
}
@Override
public 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】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值