行为模式之命令模式

编程

1 概述

命令模式" title="命令模式">命令模式(Command Pattern),是将请求封装成一系列命令对象,以解耦请求发起者和请求接收者的一种行为模式。

2 命令模式

正常情况下,请求发送者和请求接收者是相互耦合的,发送者直接调用接收者相关的方法,直接交互。

用命令模式进行改造,将两者交互的媒介----命令单独抽离出来,使得发送者和接收者相互独立,只依赖于命令对象,提高了扩展性和可维护性。同时,通过命令模式,我们还能完成一些高级操作,如撤销命令,方法参数化,命令入队,批量命令等等。

3 案例

通过一个简单的例子加深对命令模式的理解。小时候我们都玩过遥控赛车,赛车可以根据遥控器的按钮,执行相应的动作。我们作为命令的发送者,其实并不直接跟赛车交互,而是通过遥控器的指令来操作赛车:

public interface RemoteControlCar {

void moveForward();

void turnLeft();

void turnRight();

void moveBackward();

}

//请求接收者

public class RemoteControlCarImpl implements RemoteControlCar {

[@Override](https://my.oschina.net/u/1162528)

public void moveForward() {

System.out.println("The car is moving forward!");

}

[@Override](https://my.oschina.net/u/1162528)

public void turnLeft() {

System.out.println("The car turns left!");

}

[@Override](https://my.oschina.net/u/1162528)

public void turnRight() {

System.out.println("The car turns right!");

}

[@Override](https://my.oschina.net/u/1162528)

public void moveBackward() {

System.out.println("The car is moving backward!");

}

}

//命令接口,支持回退操作

public interface RemoteControlCommand {

void execute();

void undo();

}

public class ForwardCommand implements RemoteControlCommand {

RemoteControlCar rcCar;

public ForwardCommand(RemoteControlCar rcCar) {

this.rcCar = rcCar;

}

[@Override](https://my.oschina.net/u/1162528)

public void execute() {

rcCar.moveForward();

}

@Override

public void undo() {

rcCar.moveBackward();

}

}

public class BackwardCommand implements RemoteControlCommand {

RemoteControlCar rcCar;

public BackwardCommand(RemoteControlCar rcCar) {

this.rcCar = rcCar;

}

@Override

public void execute() {

rcCar.moveBackward();

}

@Override

public void undo() {

rcCar.moveForward();

}

}

public class TurnLeftCommand implements RemoteControlCommand {

RemoteControlCar rcCar;

public TurnLeftCommand(RemoteControlCar rcCar) {

this.rcCar = rcCar;

}

@Override

public void execute() {

rcCar.turnLeft();

}

@Override

public void undo() {

rcCar.turnRight();

}

}

public class TurnRightCommand implements RemoteControlCommand {

RemoteControlCar rcCar;

public TurnRightCommand(RemoteControlCar rcCar) {

this.rcCar = rcCar;

}

@Override

public void execute() {

rcCar.turnRight();

}

@Override

public void undo() {

rcCar.turnLeft();

}

}

public interface CarPlayer {

void play();

void undo();

void setCommand(RemoteControlCommand command);

}

// 命令发送者,将请求委托给命令对象来完成。通过设置不同的命令,完成不同的操作

public class Kid implements CarPlayer {

RemoteControlCommand command;

public Kid(RemoteControlCommand command) {

this.command = command;

}

@Override

public void setCommand(RemoteControlCommand command) {

this.command = command;

}

@Override

public void play() {

command.execute();

}

@Override

public void undo() {

command.undo();

}

}

public class Test {

public static void main(String[] args) {

RemoteControlCar remoteControlCar = new RemoteControlCarImpl();

RemoteControlCommand moveCommand = new ForwardCommand(remoteControlCar);

RemoteControlCommand turnLeftCommand = new TurnLeftCommand(remoteControlCar);

RemoteControlCommand turnRightCommand = new TurnRightCommand(remoteControlCar);

RemoteControlCommand stopCommand = new BackwardCommand(remoteControlCar);

// 需要完成不同的操作,只需设置不同的命令

CarPlayer kid = new Kid(moveCommand);

kid.play();

kid.undo();

kid.setCommand(turnLeftCommand);

kid.play();

kid.setCommand(turnRightCommand);

kid.play();

kid.setCommand(stopCommand);

kid.play();

kid.undo();

}

}

输出:

The car is moving forward!

The car is moving backward!

The car turns left!

The car turns right!

The car is moving backward!

The car is moving forward!

在上述例子中,我们避免了CarPlayerRemoteControlCar的直接交互,将所有的复杂度都放在RemoteControlCommand中。对命令的增删改并不影响整体系统。在这里只演示了通过命令模式可以完成撤销操作;不过很容易联想,将几个命令放到一个命令集合中一起调用,便可以达到批量操作的目的;将命令放入队列,用类似生产者--消费者的模式,可以做到延迟命令/命令入队的要求。

JDK中我们熟悉线程,就是命令模式的运用。Runnable相当于是Thread对象的命令。

4 总结

命令对象是命令模式的核心,它像是一个桥梁,连接了请求调用者和接收者,并解耦了两者的关系。它使得系统扩展变得容易。

文中例子的github地址

以上是 行为模式之命令模式 的全部内容, 来源链接: utcz.com/z/517084.html

回到顶部