关于spring:设计模式学习16Java实现命令模式

57次阅读

共计 4676 个字符,预计需要花费 12 分钟才能阅读完成。

写在后面

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

学习地址

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();}
}

写在最初

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

正文完
 0