设计模式-命令模式

命令模式(Command Pattern)

命令模式(Command Pattern):将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

 

 

命令模式结构:

 

 

 

 

Command:
        定义命令的接口,声明执行的方法。
ConcreteCommand:
       具体的命令, 实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
Receiver:
        接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
Invoker:
        要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
Client:
        创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

 

//Receiver:接收者,真正执行命令的对象。
public class Light{
    public void on(){System.out.println("开灯");}
    public void off(){System.out.println(" 关灯");}
}
//Receiver:接收者,真正执行命令的对象。
public class TV{
    public void on(){System.out.println("开电视");}
    public void off(){System.out.println(" 关电视");}
}

 

//Command:定义命令的接口,声明执行的方法。
public interface Command{
    public void execute();
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class NoCommand implements Command{
    @Override
    public void execute() {System.out.println("还没有为开关绑定操作");}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class LightOnCommand implements Command{
    private Light light;
    public LightOnCommand(Light light) {this.light = light;}
    @Override
    public void execute() { light.on();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class LightOffCommand implements Command{
    private Light light;
    public LightOffCommand(Light light) {this.light = light;}
    @Override
    public void execute() { light.off();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class TVOnCommand implements Command{
    private TV tv;
    public TVOnCommand(TV tv) { this.tv = tv;}
    @Override
    public void execute() {tv.on();}
}
//ConcreteCommand:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
public class TVOffCommand implements Command{
    private TV tv;
    public TVOffCommand(TV tv) {this.tv = tv;}
    @Override
    public void execute() {tv.off();}
}

 

//Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
public class Invoker{
    private Command[] onCommands;
    private Command[] offCommands;
    public Invoker() {
        onCommands = new Command[7];
        offCommands = new Command[7];
        //初始化
        Command noCommand = new NoCommand(); 
        for (int i=0; i<7;i++){
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }
    public void setCommand(int slot,Command onCommand,Command offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    public void onButtonPush(int slot){
        onCommands[slot].execute();
    }
    public void offButtonPush(int slot){
        offCommands[slot].execute();
    }
}

 

//Client:创建具体的命令对象,并且设置命令对象的接收者。
// 注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
public class Client{
    public static void main(String[] args){
        Invoker invoker = new Invoker();

        Light light = new Light();
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        LightOffCommand lightOffCommand = new LightOffCommand(light);

        TV tv = new TV();
        TVOnCommand tvOnCommand = new TVOnCommand(tv);
        TVOffCommand tvOffCommand = new TVOffCommand(tv);

        invoker.setCommand(0,lightOnCommand,lightOffCommand);
        invoker.setCommand(1,tvOnCommand,tvOffCommand);

        invoker.onButtonPush(0);
        invoker.offButtonPush(0);
    }
}

  

 

优点:

 1、降低了系统耦合度。

 2、新的命令可以很容易添加到系统中去。

 

缺点:

 1、使用命令模式可能会导致某些系统有过多的具体命令类。

 

应用场景:

1、命令和实际的执行者分离,实际的操作都是通过invoker以及receiver去执行的

2、屏蔽了底层的复杂实现,对外提供了统一的表现

3、可以记录操作的历史记录

4、拓展性好,一方面,可以很方便地添加新的命令,如在word中添加插入html功能;另一方面,也可以把命令迁移到另一种场景下,如把word中的命令迁移到excel中

5、用户使用上,用户通过组合一些命令,可以实现宏的功能,效率更高

 

posted @ 2020-06-05 10:21  梦里前进  阅读(129)  评论(0编辑  收藏  举报