设计模式快速入门——行为型模式之命令模式(Java)

这篇系列文章将按照以下结构逐一介绍不同种类的设计模式:

1. 创建型模式

2. 结构型模式

3. 行为型模式

通过这一系列文章,深入了解这些不同类型的设计模式,以及它们如何在软件开发中发挥关键作用。


前言

在软件开发中,设计模式是一种被广泛接受的可复用解决方案,用于解决在软件设计中常见的问题。设计模式为开发人员提供了一种通用的指导,帮助他们设计和实施高质量、易维护、可扩展的软件系统。

本文将快速入门行为型模设计模式中的命令模式。
命令模式思维导图

一、命令模式简介

1.1 什么是命令模式?

命令模式是一种行为设计模式,它旨在将请求发送者(客户端)与接收者(执行请求的对象)解耦。在这个模式中,请求被封装为一个对象,从而允许我们参数化客户端操作,将请求排队或记录请求日志,以及支持可撤销的操作。

在命令模式中,核心思想是将请求抽象成命令对象,这个命令对象包含了请求的具体信息,以及执行该请求的方法。客户端负责创建命令对象并将其发送给接收者,接收者负责执行命令。这种解耦的方式使得系统更加灵活,能够更容易地扩展和修改。

1.2 为什么需要命令模式(优点)

命令模式有许多优点,包括:

  • 解耦:命令模式将请求发送者和接收者解耦,使得它们不需要直接相互了解。这提高了系统的灵活性,允许独立地修改发送者和接收者。
  • 支持撤销:命令对象可以保存执行操作的状态,从而允许撤销操作。
  • 支持排队和日志记录:可以将命令对象排队以延迟执行,也可以记录执行的命令,以便后续分析或撤销。
  • 容易扩展:可以轻松添加新的命令类,而不需要修改现有的代码。
  • 更好的代码组织:命令模式可以帮助将系统的代码更清晰地组织,将不同的命令分离开来。

1.3 命令模式的不足

命令模式也有一些不足之处,包括:

  • 增加了类和对象的数量:引入了命令对象,可能会导致类的数量增加,这可能增加代码复杂性。
  • 可能引入延迟:将请求封装成命令对象后,可能会引入一定的延迟,因为需要创建和执行命令对象。
  • 不适用于所有情况:命令模式通常用于需要撤销、排队或记录日志的情况,对于简单的请求可能会显得过于繁琐。

1.4 命令模式的结构

命令模式通常包括以下几个角色:

  • 命令(Command):声明执行操作的接口,通常包括一个 execute 方法。

  • 具体命令(Concrete Command):实现命令接口,封装了请求的具体操作。

  • 接收者(Receiver):执行命令所指定的操作。

  • 调用者(Invoker):负责存储命令对象,并在需要时执行命令。

1.5 命令模式的应用场景

命令模式适用于那些需要将请求与其执行解耦、支持撤销、排队、日志记录或动态扩展功能的应用。在这些情况下,命令模式可以提供更清晰、更灵活和更可维护的设计解决方案。

  • 需要支持撤销和重做操作: 如果你的应用需要提供用户撤销以及重做操作的功能,命令模式是一个很好的选择。命令对象可以轻松地保存操作历史,以便撤销和重做。

  • 需要支持事务: 当你需要将一系列操作封装成一个事务,以确保它们要么全部成功执行,要么全部不执行,命令模式可以派上用场。在执行每个命令时,你可以实施事务管理逻辑。

  • 需要排队请求: 命令模式允许你将请求排队,以便按照特定的顺序执行。这在多线程环境或任务调度系统中非常有用。

  • 需要记录日志: 如果你需要记录应用的操作历史或生成日志以进行分析或审计,命令模式可以用于捕获和存储操作。

  • 需要实现可插拔的功能: 命令模式允许你将新的命令类添加到系统中,而不需要修改现有的代码。这使得系统更容易扩展。

  • 需要减少发送者和接收者之间的耦合: 命令模式可以帮助解耦命令的发送者和命令的接收者,从而使系统更加灵活和容易维护。

命令模式在许多领域都有广泛的应用,包括但不限于:

  • 菜单和工具栏系统:用户可以通过点击菜单项或工具栏按钮触发命令,从而执行特定操作。
  • 遥控器系统:遥控器可以发送命令来控制电视、音响等设备。
  • 线程池管理:将任务封装成命令对象,由线程池执行。
  • 撤销和重做功能:通过保存命令历史来支持撤销和重做操作。
  • 日程安排应用:用户可以创建命令来添加、删除或编辑日程项。

二、命令模式的示例

在这个示例中,我们将使用Java编写一个简单的奶茶店场景,利用命令模式来处理顾客的点单请求。奶茶店的员工将接收不同的奶茶制作命令,执行这些命令以制作奶茶。

首先,我们定义一个命令接口 Command,其中包含了一个 execute 方法,用于执行命令:

public interface Command {
    void execute();
}

奶茶店有不同的奶茶和咖啡制作设备。我们创建 MilkTeaMakerCoffeeMaker 作为接收者,负责实际制作奶茶和咖啡:

public class MilkTeaMaker {
    public void makeMilkTea() {
        System.out.println("制作奶茶");
    }
}

public class CoffeeMaker {
    public void makeCoffee() {
        System.out.println("制作咖啡");
    }
}

接下来,我们创建具体的命令类,每个类代表一种奶茶制作请求。例如,我们创建了 MakeMilkTeaCommandMakeCoffeeCommand

public class MakeMilkTeaCommand implements Command {
    private MilkTeaMaker milkTeaMaker;

    public MakeMilkTeaCommand(MilkTeaMaker milkTeaMaker) {
        this.milkTeaMaker = milkTeaMaker;
    }

    @Override
    public void execute() {
        milkTeaMaker.makeMilkTea();
    }
}

public class MakeCoffeeCommand implements Command {
    private CoffeeMaker coffeeMaker;

    public MakeCoffeeCommand(CoffeeMaker coffeeMaker) {
        this.coffeeMaker = coffeeMaker;
    }

    @Override
    public void execute() {
        coffeeMaker.makeCoffee();
    }
}

在奶茶店中,我们创建一个 Waiter 类作为调用者,它接收顾客的点单并执行相应的命令:

public class Waiter {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void takeOrder() {
        command.execute();
    }
}

最后,我们来演示如何在客户端中使用命令模式:

public class Client {
    public static void main(String[] args) {
        MilkTeaMaker milkTeaMaker = new MilkTeaMaker();
        CoffeeMaker coffeeMaker = new CoffeeMaker();

        Command milkTeaCommand = new MakeMilkTeaCommand(milkTeaMaker);
        Command coffeeCommand = new MakeCoffeeCommand(coffeeMaker);

        Waiter waiter = new Waiter();

        waiter.setCommand(milkTeaCommand);
        waiter.takeOrder(); // 制作奶茶

        waiter.setCommand(coffeeCommand);
        waiter.takeOrder(); // 制作咖啡
    }
}

运行结果

制作奶茶
制作咖啡

这个示例演示了如何使用命令模式将奶茶店的顾客点单请求与奶茶和咖啡制作过程解耦。命令模式允许我们轻松地添加新的制作命令,而无需修改 Waiter 类,从而实现了系统的灵活性和可扩展性。


总结

命令模式是一种强大的设计模式,可用于解耦系统的各个部分,提供更灵活、可维护和可扩展的代码结构。在合适的场景下,它可以大大改善系统的设计和可维护性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值