设计模式-行为型模式-命令模式

1.命令模式的定义

命令模式将请求封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求的排队执行、记录日志、撤销等功能;

1.1 命令模式优缺点

优点

  • 降低系统的耦合度,命令模式能将调用操作的对象与实现该操作的对象解耦;
  • 增加或删除命令很方便,采用命令模式增加与删除命令不会影响其他类,满足开闭原则,扩展较为灵活;
  • 可以实现宏命令,与组合模式结合,将多个命令装配成一个组合命令(宏命令);

缺点

  • 使用命令模式可能会导致某些系统有过多的具体命令类;
  • 系统结构更加复杂;

1.2 命令模式使用场景

  • 系统需要将请求调用者和请求接收者解耦,是的调用者和接收者不直接交互;
  • 系统需要在不同的时间指定请求、将请求排队和执行请求;
  • 系统需要支持命令的撤销操作和恢复操作;

2.命令模式的原理

  • 抽象命令类(Command):定义命令接口,声明执行的方法;
  • 具体命令类(ConcreteCommand):实现命令接口,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作;
  • 实现者/接收者(Receiver):真正执行命令的对象,任何类都可能成为一个接收者,只要他能够实现命令要求实现的相应功能;
  • 调用者/请求者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象,是客户端真正触发命令并要求执行相应操作的地方,相当于使用命令对象的入口;

3.命令模式的实现

【实例】

酒店出餐流程

  • 服务员:调用者,用来发起命令;
  • 厨师:接收者,真正执行命令的对象;

【代码】

厨师-接收者(receiver)

java 复制代码
public class Chef {
    public void makeFood(int num,String foodName){
        System.out.println(num + "份," + foodName);
    }
}

抽象命令接口(Command)

java 复制代码
public interface Command {

    void execute(); //只需要定义一个统一的执行方法
}

具体命令(Concrete Command)

java 复制代码
public class OrderCommand implements Command {

    //持有接收者对象
    private Chef receiver;

    private Order order;

    public OrderCommand(Chef receiver, Order order) {
        this.receiver = receiver;
        this.order = order;
    }

    @Override
    public void execute() {
        System.out.println(order.getDiningTable() + "桌的订单: ");
        Set<String> keys = order.getFoodMenu().keySet();
        for (String key : keys) {
            receiver.makeFood(order.getFoodMenu().get(key),key);
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(order.getDiningTable() + "桌的菜已上齐.");
    }
}

服务员-调用者(Invoker)

java 复制代码
public class Waiter {

    //可以持有很多的命令对象
    private ArrayList<Command> commands;

    public Waiter() {
        commands = new ArrayList();
    }

    public Waiter(ArrayList<Command> commands) {
        this.commands = commands;
    }

    public void setCommands(Command command) {
        commands.add(command);
    }

    //发出命令 ,指挥厨师工作
    public void orderUp(){
        System.out.println("服务员: 叮咚,有新的订单,请厨师开始制作......");
        for (Command cmd : commands) {
            if(cmd != null){
                cmd.execute();
            }
        }
    }
}

客户端

java 复制代码
public class Client {

    public static void main(String[] args) {

        Order order1 = new Order();
        order1.setDiningTable(1);
        order1.getFoodMenu().put("海参刺身",1);

        Order order2 = new Order();
        order2.setDiningTable(2);
        order2.getFoodMenu().put("葱烧海参",1);

        //创建接收者
        Chef receiver = new Chef();

        //将订单和接收者封装成命令对象
        OrderCommand cmd1 = new OrderCommand(receiver,order1);
        OrderCommand cmd2 = new OrderCommand(receiver,order2);

        //创建调用者
        Waiter invoke = new Waiter();
        invoke.setCommands(cmd1);
        invoke.setCommands(cmd2);

        //将订单发送到后厨
        invoke.orderUp();
    }
}
相关推荐
杨充16 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充16 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充16 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充16 小时前
2.面向对象的特性
设计模式
杨充16 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充16 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充16 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯19 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式