博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
命令模式(Command)
阅读量:7127 次
发布时间:2019-06-28

本文共 5223 字,大约阅读时间需要 17 分钟。

  hot3.png

一:场景示例

电脑开机过程,大家都用过吧,

1.我们要摁下按钮吧,

2.接着主板“嘀”下检查各个硬件通过

3.启动操作系统

4.进入桌面

二:ok,我们就用这样的场景使用命令模式,且看代码实现,不过实现前还是先介绍下命令模式吧,哈哈

命令模式(Command):将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日子,以及撤销等操作。(尼玛这个定义太抽象的)

命令模式的 结构和说明:

/** * 命令接口,声明执行操作 * Created by Administrator on 2016/4/22. */public interface Command {    /**     * 执行命令对应的操作     */    public void execute();}
package com.dy.command;/** * 命令接受者,真正执行命令的对象 * Created by Administrator on 2016/4/22. */public class Receiver {    public  void action(){        System.out.println("正在执行命令模式...");    }}

/** * 命令实现 * 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。 * Created by Administrator on 2016/4/22. */public class CommandImpl implements Command {    private Receiver receiver;//持有相应的接受者对象    private String status;//命令对象可以有自己的状态    public CommandImpl(Receiver receiver) {        this.receiver = receiver;    }    @Override    public void execute() {        //通常调用接受者对象相应方法,由接受者真正执行命令        this.receiver.action();    }}

/** * 调用者 * 要求命令对象执行请求,通常持有命令对象,可以持有很多命令对象 * 这是客户端真正触发命令并要求命令执行相应操作的地方,相当于所有命令对象的入口 * Created by Administrator on 2016/4/22. */public class Invoker {    private Command command;//持有命令对象    /*    *设置命令     */    public void setCommand(Command command) {        this.command = command;    }    /**     * 要求命令执行请求     */    public void run(){        command.execute();    }}

/** * 创建具体命令对象,并设置命令对象的接受者 * Created by Administrator on 2016/4/22. */public class Client {    public void doCommand() {        Receiver receiver = new Receiver();  //创建接受者者        Command command = new CommandImpl(receiver);//创建命令对象        Invoker invoker = new Invoker();       //创建Invoker        invoker.setCommand(command);           //设置命令对象        invoker.run();    }}class Test{    public static void main(String[] args) {        Client client = new Client();        client.doCommand();    }}

执行结果:

正在执行命令模式...Process finished with exit code 0

三:使用命令模式来实现电脑开机

public interface MainBoard {    /**     * 定义接受者功能     */    public void open();    public void reset();}

/** * 命令接受者,真正执行命令的对象 * Created by Administrator on 2016/4/22. */public class GigaMainBoard implements MainBoard {    @Override    public void open() {        System.out.println("技嘉主板正在开机,请稍后...");        System.out.println("接通电源...");        System.out.println("设备检查...");        System.out.println("启动系统...");        System.out.println("系统启动完成,进入桌面...");    }    @Override    public void reset() {        System.out.println("====电脑开始重启===");        System.out.println("电脑关机中...");        open();        System.out.println("====电脑重启完成===");    }}

对于用户来说开机就是摁下按钮,别的什么都不想做,也不用关心。所以这里我们要把这个动作抽象下,就相当于用户发出了一个命令或请求,其他用户不care。

/** * 命令接口,声明执行操作 * Created by Administrator on 2016/4/22. */public interface Command {    /**     * 执行命令对应的操作     */    public void execute();}

按钮本身并不知道要干什么,更不会知道怎么开机,它只负责把这个命令转给主板,主板才是开机的真正执行者

/** * 命令实现 * 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。 * Created by Administrator on 2016/4/22. */public class OpenCommand implements Command {    /**     * 持有真正的命令实现-接受者     */    private MainBoard mainBoard;    public OpenCommand(MainBoard mainBoard) {        this.mainBoard = mainBoard;    }    @Override    public void execute() {        //对于命令对象根本不需要关心命令如何执行(这里指如何开机),转掉接受者方法        this.mainBoard.open();    }}

我后期有补上了重启按钮,所以代码中不要大惊小怪哦,

/** * 命令实现 * 通常持有接受者,并调用接受者的功能来完成命令要执行的操作。 * Created by Administrator on 2016/4/22. */public class ResetCommand implements Command {    /**     * 持有真正的命令实现-接受者     */    private MainBoard mainBoard;    public ResetCommand(MainBoard mainBoard) {        this.mainBoard = mainBoard;    }    @Override    public void execute() {        //对于命令对象根本不需要关心命令如何执行,转掉接受者方法        this.mainBoard.reset();    }}

再思考下用户不想和主板直接打交道,压根用户就不需要知道主板是什么就能开机。

其实这里就是解耦的问题了,怎么办?

机箱啊,用机箱封装下不就行了吗,哈哈

接下来我们提供机箱,在机箱上装好按钮(开机按钮)

/** * 机箱,本身有按钮,即持有命令对象 * 调用者 * 要求命令对象执行请求,通常持有命令对象,可以持有很多命令对象 * 这是客户端真正触发命令并要求命令执行相应操作的地方,相当于所有命令对象的入口 * Created by Administrator on 2016/4/22. */public class Box {    /**     * 开机命令     */    private Command openCommand;    private Command resetCommand;    public void setOpenCommand(Command openCommand) {        this.openCommand = openCommand;    }    public void setResetCommand(Command resetCommand) {        this.resetCommand = resetCommand;    }    /**     * 按下按钮触发方法     */    public void openButtonPressed() {        this.openCommand.execute();    }    /**     * 按下按钮出发方法     */    public void resetButtonPressed() {        this.resetCommand.execute();    }}
把主机搬到你面前

/**         * 把机箱按钮连接线插到主板上         */        MainBoard mainBoard = new GigaMainBoard();        OpenCommand openCommand = new OpenCommand(mainBoard);        ResetCommand resetCommand = new ResetCommand(mainBoard);        /**         * 给机箱安装开机按钮         */        Box box = new Box();        box.setOpenCommand(openCommand);        box.setResetCommand(resetCommand);        /**         * 摁下开机按钮         */        box.openButtonPressed();        /**         * 重启下试试         */        box.resetButtonPressed();

摁下开机和重试按钮试试效果吧,哈哈

技嘉主板正在开机,请稍后...接通电源...设备检查...启动系统...系统启动完成,进入桌面...====电脑开始重启===电脑关机中...技嘉主板正在开机,请稍后...接通电源...设备检查...启动系统...系统启动完成,进入桌面...====电脑重启完成===Process finished with exit code 0

实际开发过程中Client和Invoker可以融合在一起。

五:命令模式组装过程的调用顺序示意图

命令模式执行过程的调用顺序示意图

转载于:https://my.oschina.net/dyyweb/blog/664521

你可能感兴趣的文章
AGG第三十八课 一些不常用的坐标转换管道
查看>>
实战案例:创建支持SSH服务的镜像
查看>>
Fiddler Web Debugger简单调试头部参数
查看>>
Linux环境下发布项目(Tomcat重新启动)
查看>>
centos7配置svn服务器
查看>>
亮剑:PHP,我的未来不是梦(13)
查看>>
MYSQL主从数据同步
查看>>
javascript数组操作
查看>>
linux中父进程退出时如何通知子进程
查看>>
linux 缩减文件系统大小 LVM
查看>>
对比文件md5值实现去重文件
查看>>
C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】
查看>>
js处理中文乱码记录/nodejs+express error 413
查看>>
基于Keepalived实现LVS双主高可用集群
查看>>
SqlServer 使用脚本创建分发服务及事务复制的可更新订阅
查看>>
什么是Floating (浮动)规则?
查看>>
分布式文件系统-FastDFS
查看>>
HTML5 rotate 做仪表盘
查看>>
为什么说荆州松滋刘氏采穴堂是刘开七、刘广传的后裔
查看>>
React中使用Ant Table组件
查看>>