在一切变好之前,我们总要经历一些不开心的日子,这段日子也许很长,也许只是一觉醒来。有时候,选择快乐,更需要勇气。
一、命令模式简介
命令模式是设计模式中行为型模式的一种。它是一种数据驱动的模式,将命令封装成一个对象传递给调用者,调用者根据请求的不同寻找合适的命令对象,命令对象调用相应的接收者完成请求。
涉及到的角色
Client: 客户端,下达命令。
Invoker: 持有大量的命令,命令的调度者。
Command: 命令的抽象接口,声明命令需要实现的方法。
ConcreteCommand: 命令接口的实现,调用相应的接收者执行命令。
Receiver: 接收者,命令的实际执行者,可以是任何对象,只要能完成命令的要求就可以。
二、实现方式
下面通过代码实现来理解命令模式的作用。
场景如下:
客户端操作灯的开关、音响的开关及音量的调节等功能。通过命令模式设计出易扩展的系统。
系统中共有如下一些类:
- Client:客户端
- Command:命令接口
- RemoteInvoker:调用者
- LightOffCommand:关灯的命令
- LightOnCommand:开灯的命令
- LightReceiver:灯的开关(接收者)
- SoundOffCommand:关闭音响的命令
- SoundOnCommand:打开音响的命令
- SoundTurnDownCommand:调低音量的命令
- SoundTurnUpCommand:调高音量的命令
- SoundReceiver:音响的操作
代码实现
Client:客户端
/**
* 客户端
*
* @author ZhengNC
* @date 2020/7/21 17:52
*/
public class Client {
public static void main(String[] args) {
//创建调用者
RemoteInvoker remoteInvoker = new RemoteInvoker();
//创建接收者
LightReceiver lightReceiver = new LightReceiver();
SoundReceiver soundReceiver = new SoundReceiver();
//向调用者中添加可执行的命令
remoteInvoker.addCommand("lightOn", new LightOnCommand(lightReceiver));
remoteInvoker.addCommand("lightOff", new LightOffCommand(lightReceiver));
remoteInvoker.addCommand("soundOn", new SoundOnCommand(soundReceiver));
remoteInvoker.addCommand("soundOff", new SoundOffCommand(soundReceiver));
remoteInvoker.addCommand("soundTurnUp", new SoundTurnUpCommand(soundReceiver));
remoteInvoker.addCommand("soundTurnDown", new SoundTurnDownCommand(soundReceiver));
//发送开灯命令
remoteInvoker.execute("lightOn");
//撤销开灯命令
remoteInvoker.undo("lightOn");
//发送关灯命令
remoteInvoker.execute("lightOff");
//撤销关灯命令
remoteInvoker.undo("lightOff");
//音响的操作
remoteInvoker.execute("soundOn");
remoteInvoker.execute("soundOff");
remoteInvoker.execute("soundOn");
remoteInvoker.execute("soundTurnUp");
remoteInvoker.execute("soundTurnDown");
}
}
Command:命令接口
/**
* 命令接口
*
* @author ZhengNC
* @date 2020/7/21 17:01
*/
public interface Command {
/**
* 执行命令
*/
void execute();
/**
* 撤销命令
*/
void undo();
}
RemoteInvoker:调用者
/**
* 调用者
*
* @author ZhengNC
* @date 2020/7/21 17:42
*/
public class RemoteInvoker {
private Map<String, Command> commandMap = new HashMap<>();
/**
* 添加一条命令
*
* @param name
* @param command
*/
public void addCommand(String name, Command command){
if (commandMap.containsKey(name)){
System.out.println("此命令名已存在!");
return;
}
if (commandMap.containsValue(command)){
System.out.println("此命令已存在!");
return;
}
commandMap.put(name, command);
}
/**
* 移除一条命令
*
* @param name
*/
public void removeCommand(String name){
commandMap.remove(name);
}
/**
* 执行命令
*
* @param name
*/
public void execute(String name){
Command command = commandMap.get(name);
if (command != null){
command.execute();
}else {
System.out.println("命令不存在!");
}
}
/**
* 撤销命令
*
* @param name
*/
public void undo(String name){
Command command = commandMap.get(name);
if (command != null){
command.undo();
}else {
System.out.println("命令不存在!");
}
}
}
LightOffCommand:关灯的命令
/**
* 关灯的命令
*
* @author ZhengNC
* @date 2020/7/21 17:20
*/
public class LightOffCommand implements Command {
private LightReceiver lightReceiver;
public LightOffCommand(LightReceiver lightReceiver){
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.off();
}
@Override
public void undo() {
lightReceiver.on();
}
}
LightOnCommand:开灯的命令
/**
* 开灯的命令
*
* @author ZhengNC
* @date 2020/7/21 17:17
*/
public class LightOnCommand implements Command {
private LightReceiver lightReceiver;
public LightOnCommand(LightReceiver lightReceiver){
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.on();
}
@Override
public void undo() {
lightReceiver.off();
}
}
LightReceiver:灯的开关(接收者)
/**
* 灯的开关(接收者)
*
* @author ZhengNC
* @date 2020/7/21 17:07
*/
public class LightReceiver {
/**
* 开灯
*/
public void on(){
System.out.println("灯亮了。。。");
}
public void off(){
System.out.println("灯暗了。。。");
}
}
SoundOffCommand:关闭音响的命令
/**
* 关闭音响的命令
*
* @author ZhengNC
* @date 2020/7/21 18:21
*/
public class SoundOffCommand implements Command {
private SoundReceiver soundReceiver;
public SoundOffCommand(SoundReceiver soundReceiver){
this.soundReceiver = soundReceiver;
}
@Override
public void execute() {
soundReceiver.off();
}
@Override
public void undo() {
soundReceiver.on();
}
}
SoundOnCommand:打开音响的命令
/**
* 打开音响的命令
*
* @author ZhengNC
* @date 2020/7/21 18:21
*/
public class SoundOnCommand implements Command {
private SoundReceiver soundReceiver;
public SoundOnCommand(SoundReceiver soundReceiver){
this.soundReceiver = soundReceiver;
}
@Override
public void execute() {
soundReceiver.on();
}
@Override
public void undo() {
soundReceiver.off();
}
}
SoundTurnDownCommand:调低音量的命令
/**
* 调低音量的命令
*
* @author ZhengNC
* @date 2020/7/21 18:21
*/
public class SoundTurnDownCommand implements Command {
private SoundReceiver soundReceiver;
public SoundTurnDownCommand(SoundReceiver soundReceiver){
this.soundReceiver = soundReceiver;
}
@Override
public void execute() {
soundReceiver.turnDownVolume();
}
@Override
public void undo() {
soundReceiver.turnUpVolume();
}
}
SoundTurnUpCommand:调高音量的命令
/**
* 调高音量的命令
*
* @author ZhengNC
* @date 2020/7/21 18:21
*/
public class SoundTurnUpCommand implements Command {
private SoundReceiver soundReceiver;
public SoundTurnUpCommand(SoundReceiver soundReceiver){
this.soundReceiver = soundReceiver;
}
@Override
public void execute() {
soundReceiver.turnUpVolume();
}
@Override
public void undo() {
soundReceiver.turnDownVolume();
}
}
SoundReceiver:音响的操作
/**
* 音响的操作
*
* @author ZhengNC
* @date 2020/7/21 18:08
*/
public class SoundReceiver {
private boolean onOff = false;
private int volume = 5;
private final int maxVolume = 10;
private final int minVolume = 0;
/**
* 打开音响
*/
public void on(){
onOff = true;
System.out.println("音响打开了。。。");
}
/**
* 关闭音响
*/
public void off(){
onOff = false;
System.out.println("音响关闭了。。。");
}
/**
* 调高音量
*/
public void turnUpVolume(){
if (onOff){
if (volume < maxVolume){
volume++;
System.out.println("调高音量,当前音量:"+volume);
}else {
System.out.println("音量已经最大了");
}
}else {
System.out.println("音响处于关闭状态");
}
}
/**
* 降低音量
*/
public void turnDownVolume(){
if (onOff){
if (volume > minVolume){
volume--;
System.out.println("调低音量,当前音量:"+volume);
}else {
System.out.println("音量已经最小了");
}
}else {
System.out.println("音响处于关闭状态");
}
}
}
运行结果展示
灯亮了。。。
灯暗了。。。
灯暗了。。。
灯亮了。。。
音响打开了。。。
音响关闭了。。。
音响打开了。。。
调高音量,当前音量:6
调低音量,当前音量:5