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

2023年 9月 16日 75.1k 0

〇、小故事

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

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

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

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

一、模式定义

命令模式(Command Pattern

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

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

二、模式类图

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

三、代码实现

创建命令接口:Command.java

public interface Command {
    void execute();
}

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

public class LightOffCommand implements Command {
    private Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
}

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

public class LightOnCommand implements Command {
    private Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
}

创建无指令实现类:NoCommand.java

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

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

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

创建遥控器类:RemoteController.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

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按钮
    }
}

输出结果:

Light on!
Light off!

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

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

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

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论