您的位置:首页 > 编程语言 > Java开发

JAVA设计模式——命令模式

2018-01-29 11:04 197 查看
命令模式,又称为行动(Action)模式、交易(Transaction)模式,是一种行为型设计模式。命令模式的思想是:把一个请求或者操作封装到一个对象中,允许系统使用不同的请求把客户端参数化,从而实现对请求排队或者记录请求日志、提供命令的撤销和恢复功等能

命令模式涉及5个角色:

客户(Client):创建一个具体命令对象并确定其接收者。

抽象命令(Command):声明了一个给所有具体命令类的抽象接口。

具体命令(Concrete Command):定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操作。

请求者(Invoker):负责调用命令对象执行请求。

接收者(Receiver):负责具体实施和执行一个请求。任何一个类都可以成为接收者。

结构图:



具体代码实现:

// 接收者
public class Receiver {
public void action() {
System.out.println("hey Geek!!");
}
}

// 抽象命令
public interface Command {
void execute();
}

// 具体命令
public class ConcreteCommand implements Command {
private Receiver receiver; // 持有一个接收者引用

public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
receiver.action();
}
}

// 请求者
public class Invoker {
private Command command; // 持有一个命令引用

public Invoker(Command command) {
this.command = command;
}

public void action() {
command.execute();
}
}

// 客户
public class Client {
private Invoker invoker; // 持有一个请求者引用

public void method() {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver); // 指定接收者
invoker = new Invoker(command); // 指定命令
invoker.action(); // 执行
}
}

// 测试
class CommandTest {
public static void main(String[] args) {
Client client = new Client();
client.method();
}
}


运行结果:

hey Geek!!

可以看到请求者和接收者是松耦合的,因此要增删命令很容易就可以实现。

下面提供一个例子,一个录音机,有
play
rewind
stop
三个按键,分别对应播放、倒带、停止三个功能。另外还有个一个宏命令功能。

// 录音机,相当于接收者,实际上的功能拥有者
public class AudioPlayer {
public void play() {
System.out.println("playing...");
}

public void rewind() {
System.out.println("rewinding...");
}

public void stop() {
System.out.println("stopped!!");
}
}

// 抽象命令
public interface Command {
void execute();
}

// 播放命令
public class PlayCommand implements Command {
private AudioPlayer audioPlayer;

public PlayCommand(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}

@Override
public void execute() {
audioPlayer.play();
}
}

// 倒带命令
public class RewindCommand implements Command {
private AudioPlayer audioPlayer;

public RewindCommand(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}

@Override
public void execute() {
audioPlayer.rewind();
}
}

// 停止命令
public class StopCommand implements Command {
private AudioPlayer audioPlayer;

public StopCommand(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}

@Override
public void execute() {
audioPlayer.stop();
}
}

// 按键,相当于请求者
public class Keypad {
private Command playCommand;
private Command rewindCommand;
private Command stopCommand;

public void setPlayCommand(Command playCommand) {
this.playCommand = playCommand;
}

public void setRewindCommand(Command rewindCommand) {
this.rewindCommand = rewindCommand;
}

public void setStopCommand(Command stopCommand) {
this.stopCommand = stopCommand;
}

public void play() {
playCommand.execute();
}

public void rewind() {
rewindCommand.execute();
}

public void stop() {
stopCommand.execute();
}
}

// 抽象宏
public interface Macro {
void add(Command command); // 添加命令

void removeLast(); // 删除最后添加的命令

void execute(); // 依次执行列表中的命令
}

// 具体宏
public class MacroCommand implements Macro {
private List<Command> list = new ArrayList<>(); // 持有一个命令列表引用

@Override
public void add(Command command) {
list.add(command);
}

@Override
public void removeLast() {
list.remove(list.size()-1);
}

@Override
public void execute() {
list.forEach(Command::execute);
}
}

// 用户
public class User {
private AudioPlayer audioPlayer = new AudioPlayer();
private Command playCommand = new PlayCommand(audioPlayer);
private Command rewindCommand = new RewindCommand(audioPlayer);
private Command stopCommand = new StopCommand(audioPlayer);

// 方法一:使用普通的命令模式执行请求
public void method1() {
Keypad keypad = new Keypad();
keypad.setPlayCommand(playCommand);
keypad.setRewindCommand(rewindCommand);
keypad.setStopCommand(stopCommand);

keypad.play();
keypad.stop();
keypad.rewind();
keypad.play();
keypad.stop();
}

// 方法二:使用宏的方式执行请求
public void method2() {
Macro macro = new MacroCommand();
macro.add(playCommand);
macro.add(stopCommand);
macro.add(rewindCommand);
macro.add(playCommand);
macro.removeLast();
macro.add(stopCommand);
macro.execute();
}

}

// 测试
class CommandTest {
public static void main(String[] ar
a676
gs) {
User user = new User();
user.method1();
System.out.println("==========");
user.method2();
}
}


运行结果:

playing…

stopped!!

rewinding…

playing…

stopped!!

==========

playing…

stopped!!

rewinding…

stopped!!

总结

命令模式使得发起命令的对象——客户,和具体实现命令的对象——接收者对象完全解耦,也就是说发起命令的对象完全不知道具体实现对象是谁,也不知道如何实现。

命令模式把请求封装起来,可以动态地对它进行参数化、队列化和日志化等操作,从而使得系统更灵活。

命令模式中的命令对象能够很容易地组合成复合命令,也就是宏命令,从而使系统操作更简单,功能更强大。

由于发起命令的对象和具体的实现完全解耦,因此扩展新的命令就很容易,只需要实现新的命令对象,然后在装配的时候,把具体的实现对象设置到命令对象中,然后就可以使用这个命令对象,已有的实现完全不用变化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 设计模式 命令