写在后面

  • 记录学习设计模式的笔记
  • 进步对设计模式的灵活运用

学习地址

https://www.bilibili.com/vide...

https://www.bilibili.com/vide...

参考文章

http://c.biancheng.net/view/1...

我的项目源码
https://gitee.com/zhuang-kang/DesignPattern

18,命令模式

18.1 命令模式的定义和特点

命令(Command)模式的定义如下:将一个申请封装为一个对象,使发出请求的责任和执行申请的责任宰割开。这样两者之间通过命令对象进行沟通,这样不便将命令对象进行贮存、传递、调用、减少与治理。

命令模式的次要长处如下。

  1. 通过引入中间件(形象接口)升高零碎的耦合度。
  2. 扩展性良好,减少或删除命令十分不便。采纳命令模式减少与删除命令不会影响其余类,且满足“开闭准则”。
  3. 能够实现宏命令。命令模式能够与组合模式联合,将多个命令装配成一个组合命令,即宏命令。
  4. 不便实现 Undo 和 Redo 操作。命令模式能够与前面介绍的备忘录模式联合,实现命令的撤销与复原。
  5. 能够在现有命令的根底上,减少额定性能。比方日志记录,联合装璜器模式会更加灵便。

其毛病是:

  1. 可能产生大量具体的命令类。因为每一个具体操作都须要设计一个具体命令类,这会减少零碎的复杂性。
  2. 命令模式的后果其实就是接管方的执行后果,然而为了以命令的模式进行架构、解耦申请与实现,引入了额定类型构造(引入了申请方与形象命令接口),减少了了解上的艰难。不过这也是设计模式的通病,形象必然会额定减少类的数量,代码抽离必定比代码聚合更加难了解。

18.2 命令模式的构造与实现

18.2.1 命令模式的构造

  1. 形象命令类(Command)角色:申明执行命令的接口,领有执行命令的形象办法 execute()。
  2. 具体命令类(Concrete Command)角色:是形象命令类的具体实现类,它领有接收者对象,并通过调用接收者的性能来实现命令要执行的操作。
  3. 实现者/接收者(Receiver)角色:执行命令性能的相干操作,是具体命令对象业务的真正实现者。
  4. 调用者/请求者(Invoker)角色:是申请的发送者,它通常领有很多的命令对象,并通过拜访命令对象来执行相干申请,它不间接拜访接收者。

18.2.2 代码实现

关系类图

Command

package com.zhuang.command;/** * @Classname Command * @Description 形象命令类 * @Date 2021/3/27 10:25 * @Created by dell */public interface Command {    void execute(); // 只须要定义一个对立的执行办法}

OrderCommand

package com.zhuang.command;/** * @Classname OrderCommand * @Description  具体命令类 * @Date 2021/3/27 10:25 * @Created by dell */public class OrderCommand implements Command{    //持有接受者对象    private SeniorChef receiver;    private Order order;    public OrderCommand(SeniorChef receiver, Order order) {        this.receiver = receiver;        this.order = order;    }    @Override    public void execute() {        System.out.println(order.getDiningTable()+"桌的订单:");        for (String key : order.getFoodDic().keySet()) {            receiver.makefood(order.getFoodDic().get(key),key);        }        try {            Thread.sleep(1000); //模仿做饭 睡眠1秒        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(order.getDiningTable()+"桌的饭弄好了");    }}

Order

package com.zhuang.command;import java.util.HashMap;import java.util.Map;/** * @Classname Order * @Description 订单类 * @Date 2021/3/27 10:34 * @Created by dell */public class Order {    // 餐桌号码    private int diningTable;    //用来存储餐名并记录    private Map<String, Integer> foodDic = new HashMap<String, Integer>();    public int getDiningTable() {        return diningTable;    }    public void setDiningTable(int diningTable) {        this.diningTable = diningTable;    }    public Map<String, Integer> getFoodDic() {        return foodDic;    }    public void setFoodDic(String name, int num) {        foodDic.put(name, num);    }}

SeniorChef

package com.zhuang.command;/** * @Classname SeniorChef * @Description 厨师类 * @Date 2021/3/27 10:27 * @Created by dell */public class SeniorChef {    //大厨师类 是命令的Receiver    public void makefood(int num, String foodName) {        System.out.println(num + "份" + foodName);    }}

Waitor

package com.zhuang.command;import java.util.ArrayList;/** * @Classname Waitor * @Description 服务员类 * @Date 2021/3/27 10:30 * @Created by dell */public class Waitor {    //能够持有很多命令对象    private ArrayList<Command> commands;    public Waitor() {        commands = new ArrayList<Command>();    }    public void setCommands(Command cmd) {        commands.add(cmd);    }    //收回命令 订单来了 大厨师开始执行命令    public void orderUp() {        System.out.println("来活了...");        for (int i = 0; i < commands.size(); i++) {            Command cmd = commands.get(i);            if (cmd != null) {                cmd.execute();            }        }    }}

Client

package com.zhuang.command;/** * @Classname Client * @Description 命令模式 测试类 * @Date 2021/3/27 10:44 * @Created by dell */public class Client {    public static void main(String[] args) {        //创立order        Order order1 = new Order();        order1.setDiningTable(1);        order1.getFoodDic().put("西红柿炒鸡蛋", 1);        order1.getFoodDic().put("罐装可乐", 2);        Order order2 = new Order();        order2.setDiningTable(2);        order2.getFoodDic().put("酸溜土豆丝", 1);        order2.getFoodDic().put("王老吉", 1);        //创立接受者        SeniorChef receiver = new SeniorChef();        //将订单和接受者封装成命令对象        OrderCommand cmd1 = new OrderCommand(receiver, order1);        OrderCommand cmd2 = new OrderCommand(receiver, order2);        //创立调用者 waitor        Waitor invoke = new Waitor();        invoke.setCommands(cmd1);        invoke.setCommands(cmd2);        //将订单给柜台 呼叫厨师        invoke.orderUp();    }}

18.3 命令模式利用场景

  • 零碎须要将申请调用者和申请接收者解耦,使得调用者和接收者不间接交互。
  • 零碎须要在不同的工夫指定申请、将申请排队和执行申请。
  • 零碎须要反对命令的撤销(Undo)操作和复原(Redo)操作。

18.4 JDK源码解析

Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start办法就是其执行办法

//命令接口(形象命令角色)public interface Runnable {    public abstract void run();}//调用者public class Thread implements Runnable {    private Runnable target;        public synchronized void start() {        if (threadStatus != 0)            throw new IllegalThreadStateException();        group.add(this);        boolean started = false;        try {            start0();            started = true;        } finally {            try {                if (!started) {                    group.threadStartFailed(this);                }            } catch (Throwable ignore) {            }        }    }        private native void start0();}

会调用一个native办法start0(),调用零碎办法,开启一个线程。而接收者是对程序员凋谢的,能够本人定义接收者。

/** * jdk Runnable 命令模式 *        TurnOffThread : 属于具体 */public class TurnOffThread implements Runnable{     private Receiver receiver;         public TurnOffThread(Receiver receiver) {         this.receiver = receiver;     }     public void run() {         receiver.turnOFF();     }}
/** * 测试类 */public class Demo {     public static void main(String[] args) {         Receiver receiver = new Receiver();         TurnOffThread turnOffThread = new TurnOffThread(receiver);         Thread thread = new Thread(turnOffThread);         thread.start();     }}

写在最初

  • 如果我的文章对你有用,请给我点个,感激你!
  • 有问题,欢送在评论区指出!