《一天一模式》— 命令模式

1、命令模式的概念

将“请求”封装成对象,以便使用不一样的请求、队列或者日志来参数化其余对象。命令模式也支持可撤销的操做。 java

2、何时使用命令模式

调用者与实现者一般是一种紧耦合的关系,但某些场合,好比须要对行为进行记录、撤销或重作、事务等处理时,这种没法抵御变化的紧耦合的设计就不太合适。 我一般这么理解命令模式,某些业务场景,一族对象会有一组命令,以命令的角度为主定义命令对象(有执行和撤回两种操做),而后把执行的过程委托给对象。this

什么是一族对象?举个例子,就是奔驰汽车、宝马汽车、奥迪汽车等。spa

什么是一组命令?举个例子,就是远程控制汽车时的开门命令、开空调命令、开天窗命令等。线程

这种状况就可使用命令模式。使用命令模式有下降耦合、可扩展、可读性高、使用方便(可撤回)等等的好处。设计

具体咱们来看一下,如何用Java代码实现命令模式。日志

3、怎么使用命令模式

3.1 实现方式

仍是以上面的需求为例子,使用命令模式对上面的业务进行实现,下面是类图和代码:code

代码以下:对象

// 车辆抽象类
public abstract class Vehicle {

    abstract void openDoor();

    abstract void openWindow();

}

public class Audi extends Vehicle {

    void openDoor() {
        System.out.println("奥迪:开门。");
    }

    void openWindow() {
        System.out.println("奥迪:开窗。");
    }

}

public class Benz extends Vehicle {

    void openDoor() {
        System.out.println("奔驰:开门。");
    }

    void openWindow() {
        System.out.println("奔驰:开窗。");
    }

}

// 命令模式接口
public interface Command {

    void execute();

}

// 开门命令
public class OpenDoorCommand implements Command {

    private Vehicle vehicle;

    public OpenDoorCommand(Vehicle vehicle) {
        this.vehicle = vehicle;
    }

    public void execute() {
        vehicle.openDoor();
    }

}

// 开窗命令
public class OpenWindowCommand implements Command {

    private Vehicle vehicle;

    public OpenWindowCommand(Vehicle vehicle) {
        this.vehicle = vehicle;
    }

    public void execute() {
        vehicle.openWindow();
    }

}

public class Client {

    public static void main(String[] args) {
        // 建立开门命令
        Command openDoorCommand = new OpenDoorCommand(new Benz());
        // 建立开窗命令
        Command openWindowCommand = new OpenWindowCommand(new Audi());
        // 执行2个命令
        openDoorCommand.execute();
        openWindowCommand.execute();
    }

}

//输出:
//奔驰:开门。
//奥迪:开窗。

3.2 命令模式的好处

使用命令的模式的好处以下:blog

  • 可读性高:从语义上可直接阅读到动做,对外提供了统一的表现;
  • 拓展性高:能够很方便地添加新的命令,也能够控制命令的撤回或重复执行;
  • 耦合性低:解除了调用者与具体实现的耦合, 屏蔽了底层的复杂实现;

3.3 注意事项

功能足够简单。若是功能自己比较简单,则不建议引入命令模式,它会带来更多的复杂性,以及更高的开发成本。接口

命令的意义不清晰或常常变化时,则不太适合使用命令模式。

通常来讲,尽可能设计傻瓜式命令,它只懂得调用一个接收者的一个行为(单一职责)。

4、总结

如何实现撤销命令,是一直值得讨论的问题,面相扩展性来讲,能够遵循一个设计方式:

不要只是记录最后一个命令,而使用一个堆栈(后进先出)记录操做过的每个命令。而后,无论何时执行撤销,你均可以从堆栈中取出最上层的命令,而后执行undo()方法来撤销它。

最后说一些其余的,命令模式还能够有更多的用途,好比使用在队列请求和日志请求。

想象一下,有一个工做队列(先进先出),你在某一端添加命令,而后另外一端则是线程,线程从队列中取出一个命令,而后调用它的execute()方法,等待这个调用完成,而后丢弃该命令,执行下一个……

在想象一下,某些应用须要咱们将全部的动做都记录在日志中,并能在系统死机后,从新调用这些动做恢复到以前的状态。咱们能够在执行命令的时候,将历史记录存储在磁盘中。一旦系统死机重启后,咱们就能够将命令对象读取出来从新执行execute()方法。

以上就是我对命令模式的一些理解,有不足之处请你们指出,谢谢。

相关文章
相关标签/搜索