嗨,伙计!刷到这篇文章就是有缘人,在阅读这篇文章前我有一些建议:
1、本篇文章大概2000多字,阅读时间长2-3分钟;
2、设计模式属于程序的设计思想、方法类的内容,阅读一遍,在理解上不一定会很透彻,建议收藏起来,有空都看看,书读百遍,其义自现嘛;
3、创作不易,免费的点赞、关注,请走一走,算是对博主一些鼓励,让我更有动和输出更多干货内容嘛;
命令模式(Command Pattern)是一种行为型设计模式,它将请求和处理分开,使得请求发送者和接收者解耦,从而降低系统的耦合度。在命令模式中,请求被封装为一个独立的对象,并且将其参数化,以便在不同的请求中传递不同的参数。
在命令模式中,请求被封装为一个对象,从而可以将请求的调用者与实现者分离开来。这降低了系统的耦合度,使得不同的调用者可以发送不同的请求给同一个接收者,而不需要修改接收者的代码。同时,命令模式还提供了对事务进行建模的方法,可以实现对事务的撤销、重做等操作。其核心角色主要有以下几个核心组成部分:
通过命令模式,客户端与调用者之间的耦合可以被解耦,客户端只需创建具体的命令对象并将其传递给调用者,而不需要了解具体的接收者和操作细节。这样可以实现请求的发送者和接收者之间的解耦,并且支持对请求进行排队、记录日志、撤销和重做等操作。
理解了命令模式的定义、核心角色以及各核心角色的功能作用,如何实现就变得很简单,下面以生活中一个事情为例来说明一下如何实现命令模式。在生活中,下班回家后,坐在沙发上用遥控器打开电视是一个很常见的事情。如果写一段程序来实现用遥控器打开电视这个过程,使用命令模式就是一个很好的选择。遥控器本身就是一个命令的接收者,而打开电视这个动作实现上就是一个指令。
1、声明一个实体电视的遥控器类,也就是具体的指令接收者;
/**
* 遥控器
*/
public class RemoteControl {
public void onGreenButton(){
System.out.println("打开电视");
}
public void onRedButton(){
System.out.println("关闭电视");
}
public void onButton2_1(){
System.out.println("河南卫视");
}
public void onButton2_2(){
System.out.println("北京卫视");
}
public void onButton2_3(){
System.out.println("山东卫视");
}
public void onDefaultButton(){
System.out.println("中央电视台");
}
}
2、声明一个抽象指令接口,在其中定义一个抽象指令执行内容方法,供具体的指令类去实现;
/**
* 抽象命令接口
*/
public interface Command {
void execute();
}
3、声明具体按钮指令,实现于抽象接口中,重写抽象方法的具体实现,如打开电视、关闭电视;
/**
* 打开指令
*/
public class OpenCommand implements Command{
private RemoteControl remoteControl;
public OpenCommand(RemoteControl remoteControl) {
this.remoteControl = remoteControl;
}
@Override
public void execute() {
this.remoteControl.onGreenButton();
}
}
/**
* 关闭指令
*/
public class CloseCommand implements Command {
private RemoteControl remoteControl;
public CloseCommand(RemoteControl remoteControl) {
this.remoteControl = remoteControl;
}
@Override
public void execute() {
this.remoteControl.onRedButton();
}
}
4、声明一个指令调用者,持有一个具体的指令对象,即遥控器上具体的按钮指令;
/**
* 命令执行器
*/
public class CommandInvoker {
private Command command;
public CommandInvoker(Command command) {
this.command = command;
}
public void executeCommand(){
this.command.execute();
}
}
5、编写客户端,将具体的遥控器对象、具体的指令整合在一起,执行具体的业务操作;
public class Client {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Command command=new OpenCommand(remoteControl);
CommandInvoker commandInvoker = new CommandInvoker(command);
commandInvoker.executeCommand();
command=new CloseCommand(remoteControl);
commandInvoker=new CommandInvoker(command);
command.executeCommand();
}
}
相信现在大家都了解这样一个事实:现在的电视机真是相当的难用,广告多的不行,各种套娃式的收费,但是我观察到一个也比较恶心的现象,现在遥控器上面的数字按钮没有了,看上去很简洁,实际上使用体验并不好。那么如果把这些数字按钮再加上去,我想看哪个电视台直接就按哪个,岂不妙哉?在命令模式的基础上来扩展类似的需求非常简单:
1、增加数字按钮指令;
/**
* 数字指令
*/
public class NumberCommand implements Command{
private int number;
private RemoteControl remoteControl;
public NumberCommand(RemoteControl remoteControl) {
this.remoteControl = remoteControl;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public void execute() {
switch (number){
case 21:
this.remoteControl.onButton2_1();
break;
case 22:
this.remoteControl.onButton2_2();
break;
case 23:
this.remoteControl.onButton2_3();
break;
default:
this.remoteControl.onDefaultButton();
break;
}
}
}
2、升级一下原来的遥控器的相关业务即可,原先的其他指令按钮,如打指令按钮、关闭指令按钮等,不用变化;
public class Client {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Command command=new NumberCommand(remoteControl);
CommandInvoker commandInvoker=new CommandInvoker(command);
commandInvoker.executeCommand();
((NumberCommand) command).setNumber(21);
commandInvoker.executeCommand();
((NumberCommand) command).setNumber(22);
commandInvoker.executeCommand();
}
}
具有以下特征的业务场景,都是比较适合使用命令行模式的,如:
命令模式是一种行为型设计模式,它允许将请求或操作封装成对象,从而解耦了请求发送者和接收者之间的耦合关系,具有解耦、抽象、事务支持、撤销支持、日志记录和宏命令等优点,但也存在具体命令类过多、实现复杂度高和设计难度大等缺点。在使用命令模式时,需要根据具体的应用场景和需求来权衡其优劣。
总之,命令模式是一种非常实用的设计模式,它可以提高系统的灵活性和可维护性,使得代码更加清晰、易于理解和扩展,强烈建议在合适的场景中使用它。