Java设计模式之命令模式

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

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

一、引出问题

老王的书房藏书越来越多,每天来借书的人络绎不绝。每天有人借书、还书、老王将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 中的应用应该很好理解。

四、总结

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

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

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

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

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

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

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Java设计模式之java命令模式详解

    目录 命令模式的介绍 角色 订单案例 命令模式的优点 适用场景 示例代码 应用 宏命令----执行一组命令 示例代码 总结 JDK源码解析 Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法 总结 命令模式的介绍 命令模式是对命令的封装.命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象 每一个命令都是一个操作:请求的一方发出请求要求执行一个操作:接收的一方收到请求,并执行操作.命令模式允许请求的一方和接收的一

  • 详解Java设计模式——命令模式

    命令模式 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互解耦,任何一方都不用去依赖其他人,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的.我们看看关系图: Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象,看实现代码: public interface Com

  • Java设计模式之命令模式详解

    命令模式 定义:将请求封装成对象,这可以让你使用不同的请求.队列.或者日志来参数化其他对象. 何时使用命令模式?当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式. 在被解耦的两者之间是通过命令对象进行沟通的.命令对象封装了接收者和一个或一组动作. 调用者通过调用命令对象的execute()方法发出请求,这会使接收者的动作被调用. 调用者可以接收命令当作参数,甚至在运行时动态地进行. 优点: 1.降低了系统耦合度. 2.新的命令可以很容易添加到系统中去. 缺点:使用命令模式可能会导致

  • Java 设计模式中的命令模式详情

    目录 模式介绍 UML类图 命令模式案例 命令模式的注意事项和细节 模式介绍 命令模式(Command Pattern) :在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计. 命名模式使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦. 在命名模式中,会将一个请求封装为一个对象,以便使用不同参数来表示不同的请求(即命名),同时命令

  • Java命令设计模式详解

    将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化.用于"行为请求者"与"行为实现者"解耦,可实现二者之间的松耦合,以便适应变化.分离变化与不变的因素. 一.角色 Command 定义命令的接口,声明执行的方法. ConcreteCommand 命令接口实现对象,是"虚"的实现:通常会持有接收者,并调用接收者的功能来完成命令要执行的操作. Receiver 接收者,真正执行命令的对象.任何类都可能成为一个接收者,只要它能够实现

  • Java以命令模式设计模式

    目录 Java以命令模式设计模式 1.简单介绍 2.命令模式 Java以命令模式设计模式 1.简单介绍 意图: 将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化. 主要解决: 在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录.撤销或重做.事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适. 何时使用: 在某些场合,比如要对行为进行"记录.撤销/重做.事务"等处理,这种无法抵御变化的紧耦合是不合适的.在这种情况下,如何将

  • 深入理解Java设计模式之命令模式

    目录 一.什么是命令模式 二.命令模式的使用场景 三.命令模式的优缺点 四.命令模式的实现 五.总结 一.什么是命令模式 命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请 求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 在该类图中,我们看到三个角色: Receiver接受者角色:该角色就是干活的角色,命令传递到这里是应该被执行的 Command命令角色:需要执行的所有命令都在这里声明 Invoker调用者角色:接收到命令,并执行命

  • Java设计模式之命令模式(Command模式)介绍

    Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体,规定很多的模式,正是这个灵活性,让人有些confuse. Command定义 不少Command模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单选择一个命令时,然后会执行一些动作. 将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式,换句

  • Java超详细讲解设计模式中的命令模式

    目录 介绍 实现 个人理解:把一个类里的多个命令分离出来,每个类里放一个命令,实现解耦合,一个类只对应一个功能,在使用命令时由另一个类来统一管理所有命令. 缺点:如果功能多了就会导致创建的类的数量过多 命令模式(Command Pattern)是⼀种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调⽤对象.调⽤对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执⾏命令. 介绍 意图:将⼀个请求封装成⼀个对象,从⽽使您可以⽤不同的请求对客户进⾏参数化.

  • Java设计模式之命令模式_动力节点Java学院整理

    定义:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 类型:行为类模式 类图: 命令模式的结构 顾名思义,命令模式就是对命令的封装,首先来看一下命令模式类图中的基本结构: Command类:是一个抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令. ConcreteCommand类:Command类的实现类,对抽象类中声明的方法进行实现. Client类:最终的客户端调用类.

随机推荐