@TOC
命令模式
命令模式(Command Pattern)属于行为型模式。它是将一个请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
它是对命令的封装,每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
命令模式通过为请求与实现间引入一个抽象命令接口,解耦请求与实现,并且中间件是抽象的,它可以有不同的子类实现,因此其具备扩展性。所以,命令模式的本质是解耦命令请求与处理。
应用场景
当系统的某项操作具备命令语义时,且命令实现不稳定,那么可以通过命令模式解耦请求与实现,利用抽象命令接口使请求方代码架构稳定,封装接收方具体命令实现细节。接收方与抽象命令接口呈现弱耦合,具备良好的扩展性。
适用场景:
1、只要认为是命令的地方都可以使用命令模式 2、请求调用者和请求的接收者需要解耦,使得调用者和接收者不直接交互 3、需要抽象出等待执行的行为,比如播放操作、暂定操作等 4、需要支持命令宏,即命令组合操作生活中的应用场景比如:遥控器,播放器,点餐系统。
优缺点
优点:
1.通过引入中间件(抽象接口),解耦了命令请求与实现。 2.扩展性良好,可以很容易地增加新命令。 3.支持组合命令,支持命令队列。 4.可以在现有命令的基础上,增加额外功能。缺点:
1.具体命令类可能过多。 2.命令模式的结果其实就是接收方的执行结果,但是为了以命令的形式进行架构,解耦请求与实现,引入了额外类型结构,增加了理解上的困难主要角色
1.接收者角色(Receiver)
该类负责具体实施或执行一个请求。
2.命令角色(Command)
定义需要执行的所有命令行为。它作为接收者角色和请求者角色的中间件,解耦彼此。
3.具体命令角色ConcreteCommand)
该类内部维护一个接收者Receiver,在其execute()方法中调用接收者Receiver的相关方法。
4.请求者角色(Invoker)
接收客户端的命令,并执行命令。
命令模式的基本使用
创建接收者角色
接收者角色负责具体实施或执行一个请求。
public class Receiver { public void action() { System.out.println("接收者Receiver执行action操作"); } }创建命令角色
命令角色定义需要执行的所有命令行为,它作为接收者角色和请求者角色的中间件,解耦彼此。
public interface ICommand { void execute(); }具体命令角色
具体命令角色内部维护一个接收者Receiver,在其execute()方法中调用接收者Receiver的相关方法。
public class ConcreteCommand implements ICommand { // 直接创建接收者,不暴露给客户端 private Receiver mReceiver = new Receiver(); public void execute() { this.mReceiver.action(); } }请求者角色
请求者角色接收客户端的命令,并执行命令。
public class Invoker { private ICommand mCmd; public Invoker(ICommand cmd) { this.mCmd = cmd; } public void action() { this.mCmd.execute(); } }客户端执行
public static void main(String[] args) { ICommand cmd = new ConcreteCommand(); Invoker invoker = new Invoker(cmd); invoker.action(); } 接收者Receiver执行action操作命令模式实现播放器功能
创建接收者角色
public class Player { public void play(){ System.out.println("执行播放操作"); } public void stop(){ System.out.println("执行暂停播放操作"); } }创建命令角色
public interface IAction { void execute(); }具体命令角色
创建播放器可以接受的播放指令
public class PlayAction implements IAction { // 直接创建接收者,不暴露给客户端 private Player player; public PlayAction(Player player) { this.player = player; } public void execute() { player.play(); } }创建播放器可以接受的暂停指令
public class StopAction implements IAction { private Player player; public StopAction(Player player) { this.player = player; } public void execute() { player.stop(); } }创建请求者角色
创建控制器,类似控制面板,执行上面提供的功能即可。如此控制器就与播放器进行解耦了,如新增指令则执行新增命令即可,无需修改控制器。
public class Controller { private List<IAction> actions = new ArrayList<IAction>(); public void addAction(IAction action) { actions.add(action); } public void execute(IAction action) { action.execute(); } public void executes() { for (IAction action : actions) { action.execute(); } actions.clear(); } }