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

描述

  • 把请求封装为一个对象,把请求和执行请求的责任分开。两者之间通过命令对象进行沟通,方便命令对象进行存储,传递,管理。
  • 比如:客户找服务员订单点餐 ,服务员发送订单命令给厨师。对服务员和厨师之间的解耦。
  • 在请求里面实现业务调用。接收者和调用者之间的耦合。

角色

  • 抽象命名角色:命令的接口,声明。
  • 具体命令角色:实现抽象命令角色,发送具体要执行的命令,通常持有接收者。
  • 接收者(实现者):执行命令的对象。(厨师)
  • 调用者(请求者):客户端调用命令的入口,通常持有命令对象。(服务员)

实现

public class Test {
    public static void main(String[] args) {
        // 订单
        Order order1 = new Order();
        order1.setTableNo("1号桌");
        order1.setMenu("佛跳墙", 1);
        order1.setMenu("米饭", 2);

        Order order2 = new Order();
        order2.setTableNo("3号桌");
        order2.setMenu("蛋炒饭", 2);
        order2.setMenu("苦瓜羹", 2);

        // 厨师A
        Cook cook1 = new Cook();
        // 厨师B
        Cook cook2 = new Cook();

        // 创建不同的命令对象(命令要做得事情不大相同,指定了不同的厨师,不同的菜)
        OrderCommand command = new OrderCommand(order1, cook1);
        OrderCommand command2 = new OrderCommand(order2, cook2);

        // 调用者
        Waitor waitor = new Waitor();
        waitor.setCommand(command);
        waitor.setCommand(command2);
        // 执行订单
        waitor.placeRrder();
    }
}

// 订单
class Order {
    // 桌号
    private String tableNo;

    // 菜单 key:菜肴 value:几份
    private Map<String, Integer> menuList = new HashMap<>();

    public String getTableNo() {
        return tableNo;
    }

    public void setTableNo(String tableNo) {
        this.tableNo = tableNo;
    }

    public Map<String, Integer> getMenuList() {
        return menuList;
    }

    // 点菜
    public void setMenu(String dish, Integer num) {
        this.menuList.put(dish, num);
    }
}

// 厨师 (接收者)
class Cook {
    // 烹制
    void cooking(String dish, Integer num) {
        System.out.println("烹制:" + num + "份" + dish);
    }
}

// 抽象命令
interface Command {
    void execute(); // 执行方法
}

// 具体命令
class OrderCommand implements Command {
    // 持有接收者
    private Cook cook;
    private Order order;

    public OrderCommand(Order order, Cook cook) {
        this.cook = cook;
        this.order = order;
    }

    @Override
    public void execute() {
        System.out.println("命令执行了:开始烹饪:");
        order.getMenuList().forEach((key, val) -> {
            cook.cooking(key, val);
        });
        System.out.println("执行完毕");
    }
}

// 服务员 (调用者)
class Waitor {
    // 持有多个命令
    private List<Command> commandList = new ArrayList<>();

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

    // 发起命令
    public void placeRrder() {
        System.out.println("您的订单来了------");
        commandList.forEach(item -> {
            if (Objects.nonNull(item)) {
                item.execute();
            }
        });
        System.out.println("订单完成------");
    }
}

优点

  • 降低接收者和调用者之间的耦合度。
  • 满足开闭原则,增加或删除一个命令,不会影响其它类。
  • 与组合模式结合,可实现宏命令(多个命令装配成一个)。
  • 方便实现undo 和 redo 操作。(与备忘录结合实现:撤销恢复操作)

缺点

  • 可能导致会有过多的具体命令类。
  • 系统结构变得复杂了。

使用场景

  • 请求调用者和接收者解耦(不直接交互)。
  • 需要在不同时间指定请求,请求排队执行(队列)。
  • 需支持撤销undo操作和恢复redo操作。

JDK中的应用

  • Runnable 接口
public class Test {

    public static void main(String[] args) {

        Receiver receiver = new Receiver();

        // 具体命令 持有接收者
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                receiver.say();
            }
        };

        // 调用者,调用命令
        new Thread(runnable).start();
    }
}
class Receiver {
    void say() {
        System.out.println("接收者");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值