命令模式
命令模式(Command Pattern):是对命令的封装,每一个命令都是一个操作。首先请求的一方发出请求要求执行一个操作,然后接收的一方收到请求,并执行操作。
命令模式属于行为型模式,解耦了请求方和接收方,请求方只需要发送命令而不需要关心命令是如何被接收的、不关心命令怎么操作、也不关心命令是否被执行等。
命令模式典型的场景就是我们使用的DOS命令和Shell命令,我们通过控制台发送命令,然后控制台将命令交给真正的执行者,而控制台在这里的作用就是充当了一个中间联系人。
示例:我们就通过发送 Shell 命令来举例说明...
 package cn.liangyy.command;
/** * Linux操作系统类 */public class LinuxSystem {    public void cd(){        System.out.println("已经切换到主目录!");    }
    public void ls(){        System.out.println("已经列举出当前目录下所有文件!");    }
    public void restart(){        System.out.println("开启重启系统!");    }}
       复制代码
 
 package cn.liangyy.command;
/** * 命令接口 */public interface ICommand {    /**     * 执行命令     */    void execute();}
       复制代码
 
 package cn.liangyy.command;
/** * cd 命令类 */public class CdCommand implements ICommand {    //持有真正的命令执行者 Linux 操作系统    private LinuxSystem linuxSystem;    /**     * 执行命令     */    @Override    public void execute() {        //调用真正的执行者来执行命令        linuxSystem.cd();    }}
       复制代码
 
 package cn.liangyy.command;
/** * ls命令类 */public class LsCommand implements ICommand {    private LinuxSystem linuxSystem;    /**     * 执行命令     */    @Override    public void execute() {        linuxSystem.ls();    }}
       复制代码
 
 package cn.liangyy.command;
/** * restart命令类 */public class RestartCommand implements ICommand {    private LinuxSystem linuxSystem;    /**     * 执行命令     */    @Override    public void execute() {        linuxSystem.restart();    }}
       复制代码
 
 package cn.liangyy.command;
import java.util.ArrayList;import java.util.List;
/** * 命令的请求在类 */public class XshellInvoker {    //封装了命令的list集合    private List<ICommand> commandList = new ArrayList<>();
    public XshellInvoker(List<ICommand> commandList) {        this.commandList = commandList;    }
    /**     * 执行指定命令     * @param command     */    public void execute(ICommand command){        command.execute();    }
    /**     * 执行命令宏,即执行特定的几个命令组合     */    public void executeCdAndLs(){        for (ICommand command : commandList){            //只执行待定的命令宏            if (command instanceof LsCommand || command instanceof CdCommand){                command.execute();            }        }    }
    /**     * 执行全部命令     */    public void executeAll(){        //通过循环的方式执行每一条命令        for (ICommand command : commandList){            command.execute();        }    }}
       复制代码
 
 package cn.liangyy.command;
import java.util.ArrayList;import java.util.List;
/** * 命令模式-测试 */public class TestCommand {    public static void main(String[] args) {        //创建命令真正的执行者        LinuxSystem linuxSystem = new LinuxSystem();
        //创建三个命令        List<ICommand> commandList = new ArrayList<>();        commandList.add(new CdCommand(linuxSystem));        commandList.add(new LsCommand(linuxSystem));        commandList.add(new RestartCommand(linuxSystem));
        //初始化命令请求者        XshellInvoker xshellInvoker = new XshellInvoker(commandList);        //执行指定命令        xshellInvoker.execute(new LsCommand(linuxSystem));        System.out.println("========================");        //执行特定命令宏        xshellInvoker.executeCdAndLs();        System.out.println("========================");        //执行全部命令        xshellInvoker.executeAll();    }}
       复制代码
 
上面就是一个命令模式的标准写法。我们可以看到,因为控制器已经与命令执行者实现了解耦,后面如果想要继续扩展新的命令,那么再增加一个命令类就行了。
桥接模式、中介者模式、命令模式这三种模式我特意放在一起讲解,因为这三种模式有一个共性,都是通过一个中间者来实现解耦,我们会很容易产生误解:
桥接模式:注重的是两个维度之间的解耦,一个抽象维度,一个实现维度。
中介者模式:注重的是同事对象之间的解耦,各个同事对象是属于同一种类型的平级对象。
命令模式:其侧重的是发送方和请求方,也就是必须要有发送方和请求方才能构成一个完整的整体。像桥接如果缺少某一方只是缺少了功能,但是依然可以正常使用;而中介者就更不用说了,同事多一个少一个在技术上完全不影响。
命令模式适用场景
命令模式优点
通过引入中间件(抽象接口)解耦了请求与实现。
扩展方便,增加新命令直接增加一个对象即可。
可以支持命令的组合操作,比较灵活方便。
命令模式缺点
评论