写在后面
- 记录学习设计模式的笔记
- 进步对设计模式的灵活运用
学习地址
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)模式的定义如下:将一个申请封装为一个对象,使发出请求的责任和执行申请的责任宰割开。这样两者之间通过命令对象进行沟通,这样不便将命令对象进行贮存、传递、调用、减少与治理。
命令模式的次要长处如下。
- 通过引入中间件(形象接口)升高零碎的耦合度。
- 扩展性良好,减少或删除命令十分不便。采纳命令模式减少与删除命令不会影响其余类,且满足“开闭准则”。
- 能够实现宏命令。命令模式能够与组合模式联合,将多个命令装配成一个组合命令,即宏命令。
- 不便实现 Undo 和 Redo 操作。命令模式能够与前面介绍的备忘录模式联合,实现命令的撤销与复原。
- 能够在现有命令的根底上,减少额定性能。比方日志记录,联合装璜器模式会更加灵便。
其毛病是:
- 可能产生大量具体的命令类。因为每一个具体操作都须要设计一个具体命令类,这会减少零碎的复杂性。
- 命令模式的后果其实就是接管方的执行后果,然而为了以命令的模式进行架构、解耦申请与实现,引入了额定类型构造(引入了申请方与形象命令接口),减少了了解上的艰难。不过这也是设计模式的通病,形象必然会额定减少类的数量,代码抽离必定比代码聚合更加难了解。
18.2 命令模式的构造与实现
18.2.1 命令模式的构造
- 形象命令类(Command)角色:申明执行命令的接口,领有执行命令的形象办法 execute()。
- 具体命令类(Concrete Command)角色:是形象命令类的具体实现类,它领有接收者对象,并通过调用接收者的性能来实现命令要执行的操作。
- 实现者/接收者(Receiver)角色:执行命令性能的相干操作,是具体命令对象业务的真正实现者。
- 调用者/请求者(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(); }}
写在最初
- 如果我的文章对你有用,请给我点个,感激你!
- 有问题,欢送在评论区指出!