古时候有一天,皇帝大发善心,要大赦天下而且还要减轻赋税,于是大臣们根据皇帝不同的旨意传达不同的指令,不管是什么指令,最终都是由老百姓来执行。这就是命令模式。

一、认识命令模式

1、概念

将客户的请求传入一个对象,请求不同传入的对象也不同。因此可实现二者之间的松耦合,以便适应变化。分离变化与不变的因素。

意思是什么呢?假如皇帝想要大赦天下,那么大臣们就可以根据皇帝的意思,传达大赦天下的指令。皇帝有想要减轻赋税,大臣们可以根据皇帝旨意,传达减轻赋税的指令,皇帝的请求不同,那么大臣们传达的指令也不同。现在应该明白了吧。

2、类图

从上面这张类图我们不难发现,皇帝的最终意思就是要让老百姓去执行,但是自己又不能亲力亲为,于是只把意思跟大臣们一说,大臣们颁布传达具体的指令,最终让老百姓去执行。

这里有五个角色,我们来分析一下:

(1)抽象命令接口Command(圣旨):声明执行的方法。

(2)具体命令对象ConcreteCommand(具体圣旨):具体的命令。

(3)接受者对象Receiver(老百姓):接受者对象,真正执行命令的对象。

(4)传递命令对象Invoker(大臣):持有命令对象,要求Receiver执行请求。

(5)客户端对象Client(皇帝):创建具体命令,设置命令对象的接受者。

3、命令模式与代理模式的区别

这个模式乍一看有点像代理模式,怎么看都是大臣是一个代理,其实不是,在这里我们提前说明一下,免得你稀里糊涂看完了一头雾水,下面进行一个对比分析。

(1)在代理(委托)模式中,调用者就是委托者,执行者就是被委托者,委托者和被委托者接口定义是相同的。命令模式不同,调用者不关注执行者的接口定义是否和它一致。

我们还是拿皇帝与大臣的关系举例子,代理模式中,要求皇帝和大臣们接口定义一样,也就是执行一样的操作。但是命令模式不同,皇帝和大臣的接口定义可以不一致,皇帝可以有自己其他的想法。

(2)在调用时机上,代理模式的具体执行是只能在特定的调用者内部执行(接口相同);命令模式的具体执行可以在任何调用者内部执行(接口不相同也可以)。

意思是什么呢?在代理模式中大臣们只执行一个皇帝(同一个人,谁当皇帝都只听朱元璋的)的命令,命令模式不一样,大臣们可以执行好几个皇帝的命令,也就是说不管谁当皇帝,都只听在任皇帝的。

现在你能分清了吧,那我们就具体来看一下命令模式如何实现的。

二、代码实现命令模式

第一步:创建接受者(老百姓)

public class People {
    //执行赦免命令
    public void exePardonCommand() {
        System.out.println("老百姓执行赦免命令");
    }
    //执行减税命令
    public void exeReduceTaxCommand() {
        System.out.println("老百姓执行减税命令");
    }
}

第二步:抽象命令接口Command(圣旨)

public interface Command {
    public void execute();
}

第三步:具体命令对象ConcreteCommand(具体圣旨)

首先是大赦天下

//大赦天下
public class PardonCommand implements Command{
    People people;
    public PardonCommand(People people) {
        this.people = people;
    }
    //大臣们也不会执行,真正执行的是百姓
    @Override
    public void execute() {
        people.exePardonCommand();
    }
}

然后是减轻赋税

public class ReduceTaxCommand implements Command{
    People people;
    public ReduceTaxCommand(People people) {
        this.people = people;
    }
    //大臣们也不会执行,真正执行的是百姓
    @Override
    public void execute() {
        people.exeReduceTaxCommand();
    }
}

第四步:传递命令对象Invoker(大臣)

public class Minister {
    //大臣们把皇帝的旨意都创建好了
    private Command pardomCommand,reduceTaxCommand;
    public Minister(Command pardomCommand, Command reduceTaxCommand) {
        this.pardomCommand = pardomCommand;
        this.reduceTaxCommand = reduceTaxCommand;
    }
    //然后大臣让老百姓去真正执行就OK了
    public void pardon() {
        pardomCommand.execute();
    }
    public void reduceTax() {
        reduceTaxCommand.execute();
    }
}

第五步:客户端对象Client(皇帝)模拟整个过程

public class Emperor {
    public static void main(String[] args) {
        //老百姓
        People people=new People();
        //皇帝的指令:大赦天下和减轻赋税
        Command pardonCommand=new PardonCommand(people);
        Command reduceTaxCommand=new ReduceTaxCommand(people);
        //把命令传达给大臣
        Minister minister=new Minister(pardonCommand, reduceTaxCommand);
        //大臣们去让老百姓去执行
        minister.pardon();
        minister.reduceTax();
    }
}
//output:
//老百姓执行赦免命令
//老百姓执行减税命令

三、分析命令模式

1、使用场景

命令模式适用于“请求-响应”模式的功能,把用户的请求封装成具体的命令对象,用户请求什么,我们就调用什么命令,用户无需知道命令执行逻辑是什么。

2、优缺点

优点:将用户的请求和请求的实现实现解耦,用户有了新需求,只需要增加一个需求实现对象即可。

缺点:请求比较多的时候,会使得整个类变得庞大。

OK,这就是命令模式,如有问题还请批评指正。


更多相关文章

  1. 03 Linux的常用命令
  2. 你可能不知道的15个 Git 命令[每日前端夜话0xF5]
  3. vtp基本命令
  4. No.7 su命令中,加-号和不加-号的区别
  5. MYSQL常用命令(4)
  6. MYSQL常用命令(3)
  7. MYSQL常用命令(1)
  8. MYSQL常用命令(2)
  9. centos 基本命令1

随机推荐

  1. ubuntu16.04 x86_64下编译ffmpeg-4.0 for
  2. android强制隐藏输入法键盘(亲测可用,欢迎
  3. Android中点击按钮的事件处理实现步骤
  4. 反编译出错
  5. Android通过换载体实现再次辉煌
  6. Android中全屏无标题设置
  7. Visibility属性中invisible和gone 区别
  8. Android GPS相关文章
  9. android 用tcpdump抓取网络包
  10. Android--通过ContentResolver取得com.an