《Head First 设计模式》(六):命令模式

1. 简介

1.1 定义

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

1.2 解决的问题

通常在系统设计中,行为请求者和行为实现者是紧耦合的关系。而在一些特定的场景下,比如:需要对行为进行记录、撤销或重做、事务等处理时,需要将行为请求者和行为实现者分离开来,这时就可以用到命令模式。

1.3 模式结构
  • Command:定义命令的接口,声明执行的方法
  • ConcreteCommand:命令接口实现对象,是“命令接口”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
  • Receiver:接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能
  • Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口
  • Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行
1.4 结构类图

在这里插入图片描述

1.5 运作流程
  1. Client创建一个ConcreteCommand对象并指定他的Receiver对象
  2. 某个Invoker对象存储该ConcreteCommand对象
  3. 该Invoker通过调用Command对象的Execute操作来提交一个请求。若该命令是可撤销的,ConcreteCommand就在执行Execute操作之前存储当前状态以用于取消该命令
  4. ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求

2. 示例Demo

Command:

package com.jbp.designpattern.command;

/**
 * @ClassName: Order
 * @description: 命令接口 --- Command
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:15
 * @Version: 1.0
 **/
public interface Order {

    void execute();

}

ConcreteCommand:

package com.jbp.designpattern.command;

/**
 * @ClassName: BuyStock
 * @description: 加库存 --- ConcreteCommmand
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:39
 * @Version: 1.0
 **/
public class BuyStock implements Order{

    private Stock stock;

    public BuyStock(Stock stock) {
        this.stock = stock;
    }

    @Override
    public void execute() {
        stock.buy();
    }
}

package com.jbp.designpattern.command;

/**
 * @ClassName: SellStock
 * @description: 清库存 --- ConcreteCommmand
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:41
 * @Version: 1.0
 **/
public class SellStock implements Order{

    private Stock stock;

    public SellStock(Stock stock) {
        this.stock = stock;
    }

    @Override
    public void execute() {
        stock.sell();
    }
}

Receiver:

package com.jbp.designpattern.command;

/**
 * @ClassName: Stock
 * @description: 请求类  --- Receiver
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:16
 * @Version: 1.0
 **/
public class Stock {

    private String name = "库存一号";

    // 数量
    private int quantity = 10;

    public void buy(){
        System.out.println("名字:" + name + ",数量:" + quantity);
    }

    public void sell(){
        System.out.println("名字:" + name + ",数量:" + quantity);
    }

}

Invoker:

package com.jbp.designpattern.command;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: Broker
 * @description: 命令调用类  --- invoker
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:43
 * @Version: 1.0
 **/
public class Broker {

    private List<Order> orderList = new ArrayList<>();

    // 加库存
    public void takeOrder(Order order){
        orderList.add(order);
    }

    // 清库存
    public void placeOrders(){
        for (Order order : orderList) {
            order.execute();
        }
        orderList.clear();
    }

}

Client:

package com.jbp.designpattern.command;

/**
 * @ClassName: test
 * @description: 测试 --- Client
 * @author: JiangBeiPing
 * @create: 2021-07-23 11:50
 * @Version: 1.0
 **/
public class test {
    public static void main(String[] args) {
        Stock stock = new Stock();
        BuyStock buyStock = new BuyStock(stock);
        SellStock sellStock = new SellStock(stock);

        Broker broker = new Broker();
        broker.takeOrder(buyStock);
        broker.takeOrder(sellStock);

        broker.placeOrders();

    }
}

3. 优缺点

优点:

  • 类间解耦:调用者角色与接收者角色之间没有任何依赖关系
  • 可扩展性:Command的子类具备高扩展性
  • 可以比较容易地设计一个组合命令

缺点:
Command的子类过多(如果有过多的命令,就会有过多的Command子类)

4. 适用场景

  1. 队列请求
  2. 日志请求
  3. 系统需要将一组操作组合在一起,即支持宏命令
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值