定义
命令模式又叫指令模式,是将“请求”封装成对象,以便使用不同的请求。我们可以把不同的请求封装成不同请求对象,对于接收者来说这些类型都能识别,然后根据不同的请求对象执行不同的行为。
说明
命令模式解决了应用程序中对象的职责以及它们之间的通信方式,命令模式可以使命令发送者和接收者完全解耦,发送者和接收者之间没有直接的引用关系。发送命令的对象只知道如何下命令,不需要知道如何完成命令。
类型
行为型
使用场景
1 2
| 1. 请求调用者和请求接收者需要解耦,使得调用者和接收者不直接交互 2. 需要抽象出等待执行的行为
|
优点
1 2 3
| 1. 降低耦合 - 通过命令模式把请求的发送者和请求的接收者进行解耦 2. 容易扩展新命令或者一组命令
|
缺点
1 2
| 命令的无限扩展会增加类的数量,提高系统实现复杂度 - 针对每一个命令我们都要设计并开发一个具体的命令类
|
相关的设计模式
命令模式和备忘录模式
1
| 可以把两者结合使用,使用备忘录模式保存命令的历史记录,这样可以调用之前的命令
|
简单需求
一创业公司为了抢占市场,老板对开发部前后下达了两个命令,先使用单例架构快速开发出产品,等到抢占了市场后再扩大规模把单体结构拆成微服务架构。
命令模式演练
把命令抽象成对象,这是命令模式实现的核心

1
| 命令扩展很容易,增加命令只需封装一个命令类。如果有命令行为体根据情况修改命令行为体。
|
命令行为体
1
| 每个命令执行的具体行为在行为体中,但不是必须的,也可以不要行为体,让命令执行变得更灵活。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.design.pattern.command;
import lombok.extern.slf4j.Slf4j;
@Slf4j public class Project {
private String name;
public Project(String name){ this.name = name; }
public void monomer(){ log.info(String.format("%s项目使用单体架构开发",this.name)); }
public void microservice(){ log.info(String.format("%s项目使用微服务架构开发",this.name)); }
}
|
命令接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.design.pattern.command;
public interface Command {
void execute(); }
|
单体架构开发命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.design.pattern.command;
public class MonomerCommand implements Command {
private Project project;
public MonomerCommand(Project project){ this.project = project; }
@Override public void execute() { project.monomer(); } }
|
微服务架构开发命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package com.design.pattern.command;
public class MicroserviceCommand implements Command {
private Project project;
public MicroserviceCommand(Project project){ this.project = project; }
@Override public void execute() { project.microservice(); } }
|
命令接收者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package com.design.pattern.command;
import java.util.ArrayList; import java.util.List;
public class Staff {
private List<Command> commands = new ArrayList<>();
public void addCommand(Command command){ commands.add(command); }
public void removeCommand(Command command){ commands.remove(command); }
public void execureCommand(Command command){ command.execute(); }
public void executeCommandList(){ this.commands.stream().forEach(Command::execute); commands.clear(); }
}
|
应用层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.design.pattern.command;
import org.junit.Test;
public class Boss {
@Test public void test() throws InterruptedException { Project projectDevelopment = new Project("带你飞"); MicroserviceCommand microserviceCommand = new MicroserviceCommand(projectDevelopment); MonomerCommand monomerCommand = new MonomerCommand(projectDevelopment);
System.out.println("//-----------------------分别执行命令---------------------------/");
Staff staff = new Staff(); staff.execureCommand(microserviceCommand); staff.execureCommand(monomerCommand);
Thread.sleep(2000);
System.out.println("//-----------------------统一执行命令集-------------------------/");
staff.addCommand(microserviceCommand); staff.addCommand(monomerCommand); staff.executeCommandList();
} }
|
命令模式在源码中的使用
Runnable接口的实现类
1
| Runnable可以看成一个抽象的命令,它的实现可以理解为具体的命令实现
|