命令模式

行为型:Command(命令模式)

  命令模式:

 

  目的:其实一般设计模式就是为了解耦。也没什么特别的,命令模式实际上就是将命令的请求者和命令的执行者解耦。

  白话:领导说了,让把这个月的项目计划压缩到三个礼拜完成,还说了:"不管你用什么办法"。这句“不管你用什么办法”就是我们所说的解耦。我不需要关心你怎么去做,我只要你能实现我想达到的目的。

 

  模式结构:一般包含下面几个部分。

    Client:客户

    Invoker:命令触发者

    Command:命令

    ConcreteCommand:具体命令实现

    Receiver:命令执行者(接收者)

  还是按生活场景来做比喻,现在我们(Client)来到了一家餐厅,服务员(Invoker)帮我们下了一个订单(ConcreteCommand),交给了厨师(Receiver)。用订单来传递信息的话,服务员和厨师都不需要互相了解和沟通。

  这是Head First设计模式中的举例,其实生活中还有很多的场景会用到命令模式。但我想,没有什么会比领导跟你说不管你用什么办法,必须在这个星期内完成任务,这样的情况更让你感到深刻了。

  下面我们用一个电视遥控器的Demo来演示:

  

package top.gabin.oa.web.design.command;

/**
 * 命令接口
 * @author linjiabin on  16/5/2
 */
public interface Command {
    /**
     * 执行命令
     */
    void execute();

    /**
     * 撤销命令
     */
    void undo();
}
package top.gabin.oa.web.design.command;

/**
 * 电视接口
 * @author linjiabin on  16/5/2
 */
public interface TV {
    void powerOn();
    void powerOff();
}
package top.gabin.oa.web.design.command;

/**
 * 电源开关
 * @author linjiabin on  16/5/2
 */
public class PowerCommand implements Command{
    private TV tv;

    public PowerCommand(TV tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.powerOn();
    }

    @Override
    public void undo() {
        tv.powerOff();
    }
}
package top.gabin.oa.web.design.command;

/**
 * 乐视TV
 * @author linjiabin on  16/5/2
 */
public class LeshiTv implements TV {
    @Override
    public void powerOn() {
        System.out.println("打开电视");
    }

    @Override
    public void powerOff() {
        System.out.println("关掉电视");
    }
}
package top.gabin.oa.web.design.command;

/**
 * 遥控器
 * @author linjiabin on  16/5/2
 */
public class RemoteControl {
    // 最简单的单例模式
    private static TV tv = new LeshiTv();

    public void powerButtonOn() {
        PowerCommand powerCommand = new PowerCommand(tv);
        powerCommand.execute();
    }

    public void powerButtonOff() {
        PowerCommand powerCommand = new PowerCommand(tv);
        powerCommand.undo();
    }

}
/**
 * 命令测试类
 * @author linjiabin on  16/5/2
 */
public class TestCommand {

    @Test
    public void testCommand() {
        RemoteControl remoteControl = new RemoteControl();
        remoteControl.powerButtonOn();
        remoteControl.powerButtonOff();
    }

}

输出:

打开电视
关掉电视

  上述的Demo,主要是分离了电视厂商的功能实现和遥控器按钮点击对应的命令。就如同我们匹配了电视和遥控器,这时候遥控器持有一个电视厂商的实现,在我们点击任意遥控器按钮的同时,遥控器会将持有的电视厂商传递给命令对象,而由命令对象去操作实际电视厂商的接口。

  好处很明显,电视厂商不需要再关注遥控器的按钮是如何分布的,按下之后该执行什么操作。反正电视厂商只提供具体功能的接口,遥控器只管生成对应的命令,并将实际命令的执行者:电视厂商传递进去即可。

  这看上去似乎没什么了不起的?但你别忘了,你随时都会适配一个新的电视厂商的实现,你确定你想要让所有的遥控器按钮都绑定到一个厂商实现吗?

  不知道此时的你是否会有一种感触:哦天,要是我的老板也懂得命令模式,我是不是再也不用跟他解释我昨天是如何搞定客户的(那一些细到我请了客户吃过几次饭,都点什么菜的细节?)

原文地址:https://www.cnblogs.com/gabin/p/5453410.html