行为型之命令模式

序言

  命令模式把发出命令的责任和执行命令的责任分隔开,分别委托给不同的对象。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
  命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
  使用命令模式会导致系统增加过度的具体命令类,使得其实现不切合实际。
  命令模式涉及到5个角色,分别是:

  • 命令角色:接口或者抽象类,抽象方法包含了命令的执行操作
  • 具体命令角色:类,实现命令的执行方法,调用接受者的相应操作
  • 请求者角色:类,负责调用命令的执行请求,相关的方法,叫行动方法
  • 接受者角色:类,负责具体实施和执行1个请求,相关的方法,叫行动方法

命令模式

  电视机会有开机,关机,换台的基本命令操作,我们不需要知道其内部实现,在这里我们是客户端,而电视机可以被看做命令接受者,遥控器则可以被看做是命令请求者,我们只需要和请求者打交道即可。
  命令模式的结构如下图:

![](http://images2017.cnblogs.com/blog/946528/201708/946528-20170819100618818-561297377.png)
>套路: >1. 将接受者要执行的命令拆分,分别创建对应的命令类,并把接受者对象委托到命令类中 >2. 创建请求者类,添加所有命令的委托对象,对于各自的命令,要创建各自的行动方法
/**
 * 命令接受者-电视机
 */
public class TV {

    private int currentChannel = 0;
    //行动方法
    public void trunOn(){
        System.out.println("电视机开启");
    }
    //行动方法
    public void turnOff(){
        System.out.println("电视机关闭");
    }
    //行动方法
    public void change(int channel){
        this.currentChannel = channel;
        System.out.println("切换到频道" + currentChannel);

    }
}
/**
 * 命令接口
 */
public interface Command {
    public void execute();
}
/**
 * 打开命令
 */
public class OnCommand implements Command{

    private TV tv;
    public OnCommand(TV tv){
        this.tv = tv;
    }
    public void execute() {
        tv.trunOn();
    }
}
/**
 * 换台命令
 */
public class ChangeCommand implements Command{
    private TV tv;
    private int channel;

    public ChangeCommand(TV tv,int channel){
        this.tv = tv;
        this.channel = channel;
    }

    public void execute() {
        tv.change(channel);
    }
}
/**
 * 关闭命令
 */
public class OffCommand implements Command {
    private TV tv;

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

    public void execute() {
        tv.turnOff();
    }
}
/**
 * 复合命令,由多个连续的基本命令操作组成
 */
public class ManyCommand implements Command{

    //可设计为命令队列
    private List<Command> commands = new ArrayList<Command>();

    public void add(Command command){
        commands.add(command);
    }
    public void remove(Command command){
        commands.remove(command);
    }
    public void execute() {
        for(Command command :commands){
            command.execute();
        }
    }
}
/**
 * 命令请求者-遥控器
 */
public class Control {

    private Command offCommand;
    private Command onCommand;
    private Command changeCommand;
    private Command manyCommand;

    //行动方法
    public void turnOn(){
        onCommand.execute();
    }
    //行动方法
    public void trunOff(){
        offCommand.execute();
    }
    //行动方法
    public void change(){
        changeCommand.execute();
    }
    //行动方法
    public void exeManyCommand(){
        manyCommand.execute();
    }

    public void setOffCommand(Command offCommand) {
        this.offCommand = offCommand;
    }

    public void setOnCommand(Command onCommand) {
        this.onCommand = onCommand;
    }

    public void setChangeCommand(Command changeCommand) {
        this.changeCommand = changeCommand;
    }

    public void setManyCommand(Command manyCommand) {
        this.manyCommand = manyCommand;
    }
}
/**
 * 测试命令模式
 */
public class CommandTest {

    @Test
    public void testCommand(){

        //命令接受者
        TV tv = new TV();
        //命令,绑定接受者
        OnCommand onCommand = new OnCommand(tv);
        ChangeCommand changeCommand = new ChangeCommand(tv, 3);
        OffCommand offCommand = new OffCommand(tv);
        //命令请求者,绑定命令
        Control control = new Control();
        control.setOnCommand(onCommand);
        control.setChangeCommand(changeCommand);
        control.setOffCommand(offCommand);
        //触发
        control.turnOn();
        control.trunOff();
        control.change();

        //复合命令
        ManyCommand manyCommand = new ManyCommand();
        manyCommand.add(onCommand);
        manyCommand.add(changeCommand);
        manyCommand.add(offCommand);
        //命令请求者绑定复合命令
        control.setManyCommand(manyCommand);
        //触发
        control.exeManyCommand();
    }

}

吹牛:

  1. 命令模式将对象的请求操作和执行操作分割开来,实现解耦
  2. 命令模式使新的命令很容易地被加入到系统里。
  3. 能较容易地设计一个命令队列。
  4. 可以容易地实现对请求的撤销和恢复。

应用场景:

  • 可使用命令模式作为回调。先将行动方法注册上,然后在需要时调用。
  • 需要在不同的时间制定请求、将请求排队。1个命令对象和原先的请求发出者可以有不同的生命周期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址,命令对象可以在序列化之后传送到另外一台机器上去。

后记

posted @ 2017-08-19 10:07  吃不了兜着走  阅读(161)  评论(0编辑  收藏  举报