今天的博客主题
设计模式 ——》 设计模式之迭代器模式
命令模式 CP (Command Pattern)
定义
将一个请求封装成一个对象,使不同的请求把客户端参数化。
命令模式是对命令的封装,每一个命令都对应了一个操作:请求方发出命令,接收方执行命令对应的操作。主要是解耦了请求方和接收方,请求方只需关心请求执行的命令,而不关心命令怎么被接收以被处理的。
现在写出的代码都是请求者与实现者通常都是一种紧耦合的关系,这样更简单明了,但缺乏扩展性。不适合在某些场合使用(行为记录,撤销等)。命令模式可以通过请求与实现中间引入一个抽象的命令接口,解耦了请求与实现,中间也是抽象的,可以有不同的子类,扩展性好。
命令模式其主要本质是解耦命令的请求与处理。
其精髓是把行为封装成对象!!!
应用场景
1)语义中具备命令的操作(如shell命令,命令菜单)。
2)调用方与接收方需要解耦,不直接交互。
3)需要抽象出等待的行为,比如撤销(Undo)和恢复(Redo)等操作。
4)支持命令组合操作。
5)
优点
1)通过引入抽象接口,可以很好的解耦命令请求与实现。
2)扩展性良好,可以很方便的新增命令。
3)支持组合命令,支持命令队列。
4)可在现有命令的基础上,增加额外功能
5)
缺点
1)具体的命令类可能过多。
2)增加代码理解难度(解耦请求与实现,引入额外类型结构)
3)
源码中应用
public interface Runnable {
public abstract void run();
}
Runnable 相当于一个命令的抽象,实现了该抽象的接口都被认为一个线程。调用线程的 start() 方法之后才有资格获取 CPU 资源,不需要我们来实现去获取 CPU 资源的逻辑。在抢到 CPU 资源之后,执行 run() 方法中的内容。可以发现 Runnable 接口把用户请求和CPU执行进行了解耦。
代码示例
命令模式主要包含四种角色
接收者角色(Receiver):负责实施执行一个请求,也就是具体的命令实现。
抽象命令角色(Command):定义需要执行的所有命令。
具体命令角色(ConcreteCommand):维护一个接收者,在其执行命令方法中调用接收者的相关方法。
请求者角色(Invoker):接收客户端命令,并执行命令,维护抽象命令角色。
/**
* 场景:游戏里的人物进行移动,发出命令,人物做出相应的动作(w前进s后退a左移d右移)
* 人物攻击同样是发出命令,人物做出响应的动作(q狱血魔神e噬魂r大闹天宫) 【请自行实现呦】
*/
// 抽象命令类,只有实现了抽象命令类的具体命令才与请求者关联。最简单的抽象命令类中只包含了一个抽象的execute()方法
interface Command{
void execute();
}
// 具体命令类
class MoveForwardConcreteCommand implements Command {
private MoveForwardReceiver moveForwardReceiver;
public MoveForwardConcreteCommand(MoveForwardReceiver moveForwardReceiver){
this.moveForwardReceiver = moveForwardReceiver;
}
@Override
public void execute() {
moveForwardReceiver.forward();
}
}
class MoveBackOffConcreteCommand implements Command {
private MoveBackOffReceiver moveBackOffReceiver;
public MoveBackOffConcreteCommand(MoveBackOffReceiver moveBackOffReceiver){
this.moveBackOffReceiver = moveBackOffReceiver;
}
@Override
public void execute() {
moveBackOffReceiver.backoff();
}
}
class MoveLeftCommandConcreteCommand implements Command{
private MoveLeftReceiver moveLeftReceiver;
public MoveLeftCommandConcreteCommand(MoveLeftReceiver moveLeftReceiver){
this.moveLeftReceiver = moveLeftReceiver;
}
@Override
public void execute() {
moveLeftReceiver.left();
}
}
class MoveRightCommandConcreteCommand implements Command{
private MoveRightReceiver moveRightReceiver;
public MoveRightCommandConcreteCommand(MoveRightReceiver moveRightReceiver){
this.moveRightReceiver = moveRightReceiver;
}
@Override
public void execute() {
moveRightReceiver.right();
}
}
// 请求的接收者,也就是具体的命令实现
class MoveForwardReceiver{
public void forward(){
System.out.println("前进");
}
}
class MoveBackOffReceiver{
public void backoff(){
System.out.println("后退");
}
}
class MoveLeftReceiver{
public void left(){
System.out.println("左移");
}
}
class MoveRightReceiver{
public void right(){
System.out.println("右移");
}
}
// 请求发送者
class Invoker{
private Command command;
public Invoker(Command command){
this.command = command;
}
public void call(){
command.execute();
}
}
// 客户端调用
public class CommandPatternSample {
public static void main(String[] args) {
// 使用一种策略来维护命令集合
Map<String, Invoker> maps = new HashMap<>();
maps.put("w", new Invoker(new MoveForwardConcreteCommand(new MoveForwardReceiver())));
maps.put("s", new Invoker(new MoveBackOffConcreteCommand(new MoveBackOffReceiver())));
maps.put("a", new Invoker(new MoveLeftCommandConcreteCommand(new MoveLeftReceiver())));
maps.put("d", new Invoker(new MoveRightCommandConcreteCommand(new MoveRightReceiver())));
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
String command = scan.nextLine();
if(maps.containsKey(command)){
maps.get(command).call();
}
}
scan.close();
}
}