首页 > 其他分享 >设计模式之命令模式

设计模式之命令模式

时间:2022-08-30 09:23:40浏览次数:77  
标签:模式 命令 记录员 借书 设计模式 public

本文通过解决老王经常搞错借书人的问题,来引出行为型模式中的命令模式。为了在案例之上理解的更加透彻,我们需要了解命令模式在源码中的应用。最后指出命令模式的应用场景和优缺点。

读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云

一、引出问题

老王的书房藏书越来越多,每天来借书的人络绎不绝。每天有人借书、还书、老王将A借的书算到B头上的乌龙事件频出。老王和小王就商量着手解决这个问题。

小王提议,在老王和借书者之间再增加一个“记录员”角色,记录员只管报名字就行了,具体是借什么书由借书者自己决定就好了。

老王说:这能解决部分问题。但在真实的场景下,不可能来一个借书者“记录员”就跑一趟。而且借书者有时候会借一半临时有事就不借了。这些问题你也要考虑进去。

老王接着说:你应该,在“记录员”角色中,增加一个队列,将所有借书者都放到一个队列中,既有往队列中放命令的方法,也有从命令中移除的方法,方便“记录员”请求排队和“撤销”。

二、命令模式的概念和应用

老王提出来的正是命令模式的“白话文解释”。我们来看命令模式的官方概念:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开,解耦合。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用、增加与管理。

在命令模式中有三个角色:

抽象命令类(Command)角色: 定义命令的接口,声明执行的方法。

实现者/接收者(Receiver)(老王)角色: 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

具体命令(Concrete Command)(记录员)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

我们基于概念和角色划分,实现代码:

抽象命令类:

/**
 * 抽象命令类
 * @author tcy
 * @Date 25-08-2022
 */
public interface AbstractCommand {

    //只需要定义一个统一的执行方法
    void execute();
}

具体命令角色(老王):

/**
 * 具体命令
 * @author tcy
 * @Date 25-08-2022
 */
public class ConcreteCommand implements AbstractCommand {

    //持有接受者对象
    private String clent;

    public ConcreteCommand(String clent){
        this.clent = clent;
    }

    @Override
    public void execute() {
        System.out.println("具体执行者角色(老王):"+clent+"借书...");

    }
}

接收者(记录员):

/**
 * 接收者
 * @author tcy
 * @Date 25-08-2022
 */
public class ReceiverCommand {

    //可以持有很多的命令对象
    private ArrayList<AbstractCommand> commands;

    public ReceiverCommand() {
        commands = new ArrayList();
    }

    public void setCommand(AbstractCommand cmd){
        commands.add(cmd);
    }

    public void removeCommand(AbstractCommand cmd){
        commands.remove(cmd);
    }

    // 发出命令
    public void borrowBookMeaaage() {
        System.out.println("接受者角色(记录员):有人来借书啦...");
        //通知全部命令
        for (int i = 0; i < commands.size(); i++) {
            AbstractCommand cmd = commands.get(i);
            if (cmd != null) {
                cmd.execute();
            }
        }
    }
}

客户端(借书者):

/**
 * @author tcy
 * @Date 25-08-2022
 */
public class Client {

    public static void main(String[] args) {

        //创建接收者
        //将订单和接收者封装成命令对象
        ConcreteCommand cmd1 = new ConcreteCommand( "A");
        ConcreteCommand cmd2 = new ConcreteCommand( "B");

        //创建具体命令者
        ReceiverCommand invoker = new ReceiverCommand();
        invoker.setCommand(cmd1);
        invoker.setCommand(cmd2);

        //喊一声有人要借书
        invoker.borrowBookMeaaage();


    }

}

基于命令模式实现的代码就实现了,但是看懂代码是一回事,自己能写出来就是另外一回事了。读者最好根据案例重新仿写一遍。

三、源码中的应用

在源码中使用命令模式的典型案例就是Jdk多线程章节中的Runnable ,Runnable 相当于命令模式中的抽象命令角色。Runnable 中的 run() 方法就当于 execute() 方法。

我们知道,Java中一个类实现Runnable 接口,那么该类就认为是一个线程,就相当于命令模式中的具体命令角色。

当我们调用start()方法后,就可以与别的线程强占CPU的资源,在占用CPU的线程中就会执行run()方法。CPU的调度者就相当于具体命令角色也即记录员。Runnable 就完美的实现了用户自定义线程和CPU的解耦合。

命令模式在Runnable 中的应用应该很好理解。

四、总结

优点很明显,解耦了命令请求与实现,很容易的可以增加新命令,支持命令队列。

但是,这样会不可避免的使具体命令类过多,增加了理解上的困难。

设计模式学到这种程度,我们就会发现设计模式不是一种单一的技术,而是各种技术的综合体。

我们在学习设计模式的时候一定不要仅局限于一种模式,而是站在一定的高度去整体衡量哪种设计模式才是最优的。

有时候我们会发现,使用设计模式会让我们的代码变得更加的复杂,但以自己目前的开发经验又不能确定是否采用设计模式是一个好的选择。

归根结低,还是我们对设计模式掌握的不够熟练,这就需要我们继续深入学习设计模式,当我的学完再回头看这些问题,就很自然的迎刃而解了。

已经连续更新了数十篇设计模式博客,推荐你结合学习。

一、设计模式概述

二、设计模式之工厂方法和抽象工厂

三、设计模式之单例和原型

四、设计模式之建造者模式

五、设计模式之代理模式

六、设计模式之适配器模式

七、设计模式之桥接模式

八、设计模式之组合模式

九、设计模式之装饰器模式

十、设计模式之外观模式

十一、外观模式之享元模式

十二、设计模式之责任链模式

标签:模式,命令,记录员,借书,设计模式,public
From: https://www.cnblogs.com/tianClassmate/p/16638122.html

相关文章

  • 初识设计模式 - 工厂模式
    简介工厂设计模式(FactoryDesignPattern)是一种创建型的设计模式,它提供了一种创建对象的最佳方式,是一种代替new操作符的一种模式。在工厂模式中,创建对象不会对客户端暴......
  • HCIA学习笔记二十六:手工负载分担模式二层链路聚合
    一、链路聚合的应用场景• 链路聚合一般部署在核心结点,以便提升整个网络的数据吞吐量。二、链路聚合• 链路聚合能够提高链路带宽,增强网络可用性,支持负载分担。三......
  • gdb交互命令
    gdb交互命令启动gdb后,进入到交互模式,通过以下命令完成对程序的调试;注意高频使用的命令一般都会有缩写,熟练使用这些缩写命令能提高调试的效率;运行run:简记为r,其作用是......
  • 暑假学习6 hdfs shell命令
    命令行操作:cliHadoop的命令shell:Hadoopfs-lsfile:          操作本地的文件系统hadoopfs-lshdfs://node1:8020         ......
  • Linux命令(二)
    压缩、解压缩tar命令位于/bin目录下,它能够将用户所指定的文件或目录打包成一个文件,但不做压缩-c:创建一个新tar文件-v:显示运行过程的信息-f:指定文件名......
  • DOS 常用命令
    命令用法cdcd:显示当前所在的目录cd..:返回上一级cdXXX:进入到某个目录goto:ifXXXgotolabel:labelecholabelmove moveab将a......
  • Linux 一些常用命令
    Linux命令的分类1、帮助命令(help)2、常用系统工作命令3、常用状态检测命令4、工作目录切换命令Linux常用命令echo命令作用:在终端输出字符串或变量后提取的值格式:ech......
  • java设计模式之职责链模式(二)
    职责链模式的一个变种如下,执行某一个handler,用当前handler是否执行成功判断是否要执行下一个handler,首先我们定义一个抽象handler类,如果当前handler执行不成功,且还有下一......
  • java设计模式之职责链模式(三)
    责任链模式有很多变种。有些责任链是构成一个list,遍历调用,有一个成功就直接返回。比如DateFormatChain有些的实现方式如下所示,是通过某个Handler手动调用下一个Handler来传......
  • C语言:命令行参数
    命令行参数在图形界面普及之前都使用命令行界面。DOS和UNIX就是例子。Linux终端提供类UNIX命令行环境。命令行(commandline)是在命令行环境中,用户为运行程序输入命令的行......