趣解设计模式之《把意大利炮给我拿来!》

〇、小故事

回忆一下我们去饭店点餐,我们坐好,服务员给我们递过来菜单,我们点菜,点完菜我们就可以刷抖音或者玩王者荣耀了。那么过一会儿菜就上来了。谁做的菜? 怎么做的菜?厨师的名字叫啥?他是什么星座的?是不是程序员转行了? 我们一概不关心

再思考一个场景,我们作为公司的技术部的leader,有需求来了,说是现在我们商城的支付方式太少了,只有银联支付,很多用户反应需要微信支付和支付宝支付。那么你叫来了团队最靠谱的小李,然后跟他说下周希望商城有微信支付的功能,下下周有支付宝支付的功能。小李说没问题,然后你就去忙你自己的事儿了。两周后,支付宝和微信支付功能如期上线,你很开心,并且认为小李很给力。

还有就是战场上,司令员下达命令就是"把我的意大利炮拿出来,把XX山头给我打下来"。这就是命令,而具体怎么实现,部队里哪些人去做,不是司令员关心的,他只关心XX山头打下来没有

那么以上的三个例子,都是我们今天要介绍的设计模式的现实写照------命令模式

一、模式定义

命令模式Command Pattern

将"请求 "封装成命令对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。

为了加深模式的理解,我们假设要设计一款多功能遥控器 ,这个遥控器有一排的on开关和一排的off开关,我们可以指定某个on/off开关执行某个命令,比如开灯、关灯、打开电视等等。如下图所示:

二、模式类图

针对上面说的多功能遥控器,我们来设计对应类图,首先,需要遥控器类RemoteController ,在这个类里,包含着一排on按钮(onCommands)和一排off按钮(offCommands);其次,创建命令接口Command ,提供执行命令的方法execute();然后实现具体的指令实现类,如:LightOnCommandLightOffCommand ,当然,具体的操作灯的行为,还是在Light类中,因为这个类才是实际供应商提供给我们关于这盏灯的操作api。具体类图,请见如下所示;

三、代码实现

创建命令接口Command.java

java 复制代码
public interface Command {
    void execute();
}

创建关灯命令实现类LightOffCommand.java

java 复制代码
public class LightOffCommand implements Command {
    private Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
}

创建开灯命令实现类LightOnCommand.java

java 复制代码
public class LightOnCommand implements Command {
    private Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
}

创建无指令实现类NoCommand.java

java 复制代码
public class NoCommand implements Command {
    public void execute() {
        System.out.println("Doing nothing!");
    }
}

创建供应商所属灯的API类Light.java

java 复制代码
public class Light {
    /** 开灯操作 */
    public void on() {
        System.out.println("Light on!");
    }
    /** 关灯操作 */
    public void off() {
        System.out.println("Light off!");
    }
}

创建遥控器类RemoteController.java

java 复制代码
public class RemoteController {
    private Command[] onCommands;
    private Command[] offCommands;

    public RemoteController() {
        onCommands = new Command[4];
        offCommands = new Command[4];

        for (int i = 0; i < 4; i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }

    /** 往遥控器中添加命令 */
    public void addCommand(int slot, Command onCommand, 
                           Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    /** 按遥控器中某个开启键 */
    public void pushOnButton(int slot) {
        onCommands[slot].execute();
    }

    /** 按遥控器中某个关闭键 */
    public void pushOffButton(int slot) {
        offCommands[slot].execute();
    }
}

创建测试类CommandTest.java

java 复制代码
public class CommandTest {
    public static void main(String[] args) {
        Light light = new Light();
        RemoteController controller = new RemoteController();
        controller.addCommand(0, new LightOnCommand(light), 
                              new LightOffCommand(light));
        controller.pushOnButton(0); // 按下遥控器,第一排的ON按钮
        controller.pushOffButton(0); // 按下遥控器,第一排的OFF按钮
    }
}

输出结果

vbnet 复制代码
Light on!
Light off!

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号"爪哇缪斯" ~ \(^o^)/ ~ 「干货分享,每天更新」

相关推荐
HanhahnaH2 分钟前
Spring集合注入Bean
java·spring
未定义.2218 分钟前
电子削铅笔刀顺序图详解:从UML设计到PlantUML实现
java·软件工程·uml
雾月5525 分钟前
LeetCode 1292 元素和小于等于阈值的正方形的最大边长
java·数据结构·算法·leetcode·职场和发展
丘山子36 分钟前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
CopyLower1 小时前
在 Spring Boot 中实现 WebSockets
spring boot·后端·iphone
24k小善1 小时前
Flink TaskManager详解
java·大数据·flink·云计算
想不明白的过度思考者1 小时前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
天天扭码2 小时前
总所周知,JavaScript中有很多函数定义方式,如何“因地制宜”?(ˉ﹃ˉ)
前端·javascript·面试
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV2 小时前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试