命令模式的定义:
将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作,将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来。
角色分析:Command :声明执行操作的接口
ConcreteCommand :将一个接收者对象绑定于一个动作, 调用接收者相应的操作,以实现Execute
Client:创建一个具体命令对象并设定它的接收者。
Invoker:要求该命令执行这个请求。命令的发出者,具体发什么命令自己决定。
Receiver:知道如何实现与执行一个请求相关的操作。任何类都可能作为一个接收者。
ConcreteReceiver:具体的接收者,不同的命令可能会有不同的接收者去真实完成
接下来就是用代码示例实现命令模式:
抽象的命令接收者:
/** * 命令接收者 * 真正执行命令的角色 */ public interface Receiver { /** * 执行任务方法 */ void action(); }接收者两个具体实现:
public class Designer implements Receiver { @Override public void action() { System.out.println("我是设计员,我要做产品设计"); } } public class Coder implements Receiver{ @Override public void action() { System.out.println("我是码农,我根据产品设计去实现"); } }抽象命令:
public interface Command { void execute(); }具体的命令 : 设计命令和代码命令:
public class DesignCommand implements Command { private Receiver designerReceiver; DesignCommand(){ this.designerReceiver = new Designer(); } @Override public void execute() { this.designerReceiver.action(); } } public class CodeCommand implements Command{ private Receiver codeReceiver; CodeCommand(){ this.codeReceiver = new Coder(); } @Override public void execute() { this.codeReceiver.action(); } }发命令者:
public class Invoker { private Command command; /** * 设置命令 * @param command 具体的命令 */ public void invoke(Command command) { this.command = command; } public void call(){ if (this.command != null){ this.command.execute(); } else { throw new RuntimeException("没有具体的命令,不能发出命令"); } } }测试代码:
public class CommandTest { public static void main(String[] args) { // 创建设计命令 Command designCommand = new DesignCommand(); // 创建代码命令 Command codeComamnd = new CodeCommand(); // 创建发命令者 Invoker invoker = new Invoker(); // 设置设计命令 invoker.invoke(designCommand); // 调用 invoker.call(); // 设置代码命令 invoker.invoke(codeComamnd); // 调用 invoker.call(); } }测试结果:
我是设计员,我要做产品设计 我是码农,我根据产品设计去实现命令模式的优缺点:
优点:
类间解耦 可扩展性 与其它模式组更优秀
缺点:
N个命令,N个子类,类膨胀