设计模式---命令模式

来源:互联网 发布:php截取一段字符串 编辑:程序博客网 时间:2024/06/03 18:21

定义

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

类图

这里写图片描述

理解

命令模式的关键就在“将‘请求’封装成对象”这句话,其中的”请求“指的就是”命令“。

如上类图所示,命令模式中一共有4个主要角色:抽象命令、具体命令、调用者、接收者。

  • 抽象命令:一个抽象类,一般只有一个execute()方法,用来执行命令。
  • 具体命令:抽象命令类的实例化,包含具体的接收者,实现了execute()方法,让接收者执行命令。
  • 接收者:命令的接收者,接收命令后,运行相应的方法。
  • 调用者:负责调用命令,让具体命令类执行execute()方法。

就拿点外卖来说,

  • 具体命令:就是点外卖时下的订单,订单中包含了店家和你点的食物。
  • 接收者:就是店家了。
  • 调用者:就是外卖平台的订单系统,收集订单,然后按顺序执行订单。

代码

接收者

public class ReceiverA {    public void barbecue(){        Log.e("ZXK","ReceiverA---烧烤");    }}public class ReceiverB {    public void hamburger(){        Log.e("ZXK","ReceiverB---汉堡");    }}public class ReceiverC {    public void noodle(){        Log.e("ZXK","ReceiverC---面条");    }}

命令接口及具体命令

public interface Order {    public void execute();}public class OrderA implements Order {    private ReceiverA receiverA;    public OrderA(ReceiverA receiverA) {        this.receiverA = receiverA;    }    @Override    public void execute() {        receiverA.barbecue();    }}public class OrderB implements Order {    private ReceiverB receiverB;    public OrderB(ReceiverB receiverB) {        this.receiverB = receiverB;    }    @Override    public void execute() {        receiverB.hamburger();    }}public class OrderC implements Order {    private ReceiverC receiverC;    public OrderC(ReceiverC receiverC) {        this.receiverC = receiverC;    }    @Override    public void execute() {        receiverC.noodle();    }}

调用者

public class Invoker {    List<Order> orderList;    public Invoker() {        orderList = new ArrayList<>();    }    public void addOrder(Order order){        orderList.add(order);    }    public void cook(){        for(int i = 0;i<orderList.size();i++){            orderList.get(i).execute();        }    }}

测试

/** * 创建三家店 */ReceiverA receiverA = new ReceiverA();ReceiverB receiverB = new ReceiverB();ReceiverC receiverC = new ReceiverC();/** * 对每家店创建一个订单 */Order orderA = new OrderA(receiverA);Order orderB = new OrderB(receiverB);Order orderC = new OrderC(receiverC);/** * 下订单 */Invoker invoker = new Invoker();invoker.addOrder(orderA);invoker.addOrder(orderB);invoker.addOrder(orderC);/** * 执行订单 */invoker.cook();

这里写图片描述

宏命令

接着上面的例子,如果我想一下子点这三家的三种食物怎么办?这时候就需要用到宏命令。

代码

public class MacroCommond implements Order {    Order[] orders;    public MacroCommond(Order[] orders) {        this.orders = orders;    }    @Override    public void execute() {        for(Order order:orders){            order.execute();        }    }}

测试

/** * 创建三家店 */ReceiverA receiverA = new ReceiverA();ReceiverB receiverB = new ReceiverB();ReceiverC receiverC = new ReceiverC();/** * 每家店创建一个订单 */Order orderA = new OrderA(receiverA);Order orderB = new OrderB(receiverB);Order orderC = new OrderC(receiverC);Order[] orders = {orderA,orderB,orderC};/** * 利用宏命令下订单 */MacroCommond macroCommond = new MacroCommond(orders);macroCommond.execute();

这里写图片描述

总结

命令模式中将”命令“封装成对象,具体命令类中包含了命令被执行时,需要调用的接收者类及其被调用的相应方法。调用者的作用在于存储命令对象,以及调用命令,让命令执行execute()方法,然后命令又调用其中存储的接收者类,执行相应方法。

优点:

  • 命令被封装起来了,客户端需要执行什么命令,调用就是,不需要知道命令里的逻辑。
  • 可以在简单命令的基础上再创建宏命令,不需要从头写起,组合就行。

缺点:

  • 结构简单的时候,使用命令模式挺浪费的,也挺麻烦的。
原创粉丝点击