23种设计模式之命令模式

这里写目录标题

命令模式简介

亦称:动作、事务、Action、Transaction、Command
意图: 命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。

UML图

      当学了这个命令模式后,又一次体会到编程的艺术,明明一个看似很简单的事,却要用“复杂”的方法来实现,就像在之前我多次说到的,其实并不是“复杂”,并不是“难”,而是自己基本功太弱,这些看似“复杂”的设计并不是故弄玄机卖弄,仔细学习过后才发现之精妙。比如今天要说的命令模式,书中举的例子非常典型。去路边摊买烧烤,我是客户,老板是烤烧烤的,这个可以简单画一下UML类结构图。

      这是我们一贯的思维,烤羊肉、烤鸡翅作为烤烧烤者的两个类,我作为买烧烤者(客户端)直接通过烤烧烤者类调用“烤羊肉”、“烤鸡翅”方法,这实际上是非常紧的耦合,客户多了,烧烤摊就会乱。所以我们要想如何来将代码解耦呢?同样,还是这个例子,有路边摊,但是也有烧烤店,在烧烤店里服务员给我们一个菜单,服务员将我们点好的菜单再转交给烤串师傅,在这期间我们不必关心是谁烤的,我们也不会一直盯着他烤串,我们吃多吃少吃咸吃淡这一切在菜单里都有记录,我们坐等上烤串就可以了。通过烧烤店我们就可以引申出一个设计模式——命令模式。

      我们思考,“烧烤店模式”在中间多了一个服务员,通过服务员发送“命令”给师傅来给我们烤串,具体的烤串过程,我不关心服务员也不关心。

      一个基本的雏形好像就出来了,我们再继续,我们把烤羊肉、烤鸡翅当做一个一个命令,就可以将命令抽象出来了。

      这好像差不多了,不过我们的烤串师傅呢?我们说了烤串师傅才是具体负责烤羊肉、烤鸡翅的,所以就是烤羊肉、烤鸡翅依赖于烤串师傅。

通过上面的UML类结构图,我们用代码来实现烧烤店的烤串场景。

在这里插入图片描述

首先我们把命令接口改为抽象类,因为我们要传递一个具体的烤串者进去。

//命令抽象类,通过构造函数可提供具体的烤串师傅
abstract class  AbstractCommand{

    BarbecueMan barbecueMan;
    public AbstractCommand(BarbecueMan barbecueMan){
        this.barbecueMan = barbecueMan;
    }

    public abstract void executeCommand();
}

实现一个具体的命令类

//烤羊肉串命令
class MuttonKebab extends AbstractCommand{

    public MuttonKebab(BarbecueMan barbecueMan) {
        super(barbecueMan);
    }

    @Override
    public void executeCommand() {
        System.out.println("开始烤羊肉串~");
    }

    @Override
    public String toString() {
        return "烤羊肉串";
    }
}

接着是服务员负责从客户这里取回菜单向师傅喊命令烤串。

class Waiter{

    List<AbstractCommand> order = new ArrayList<>();

    void setOrder(AbstractCommand command){
        order.add(command);
        System.out.println("增加订单:" + command.toString());
    }

    void cancelOrder(AbstractCommand command) {
        order.remove(command);
        System.out.println("取消订单:" + command.toString());
    }

    void notifyM(){
        for (AbstractCommand command:order) {
            command.executeCommand();
        }
    }

}

//烧烤师傅
class BarbecueMan {
    public void action(){
        System.out.println("开始执行");
    }

}

client类

public class CommandPattern {
    public static void main(String[] args) {

        BarbecueMan man = new BarbecueMan();
        MuttonKebab muttonKebab = new MuttonKebab(man);

        Waiter waiter = new Waiter();
        waiter.setOrder(muttonKebab);
        waiter.notifyM();
    }
}

运行结果

      一定要从UML类结构图开始到编码自己手动过一遍,这仅仅是学习,离实际应用还有很长的理解时间,就比如说在这里我们并没有利用多少“烤串者”这个类,但这不代表在命令模式下就不需要它。最后来总结下命令模式的优点:它能把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。最后说个题外话,对于敏捷开发原则,当我们并不清楚一个系统是否需要命令模式时,我们不用绞尽脑汁去实现,在以后的系统版本中如果需要用到命令模式,再通过代码重构为命令模式。这就涉及敏捷开发和重构了,再将设计模式学习完过后接着就是聊聊重构。

本文参考于:https://www.cnblogs.com/yulinfeng/p/5940704.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值