命令模式(Command)
思想概要
命令模式属于比较复杂的模式,我尽量用自己理解的场景来描述它。首先,设计模式的目的就是解耦,即:在设计变更时,尽量不改或者只是改很少一部分代码。在命令模式里,有两个部分是非常复杂,或者说很容易出现不易更改的代码块。第一是:命令调度部分,第二是命令具体执行部分。这两个部分能不改就不改,而命令间的顺序,命令流向不仅容易改,而且经常是变更的部分。所以评价命令模式要从是否减少了命令调度和命令执行这两个部分出发。
我们假设一个应用,用户通过脚本删除或者增加界面A或者是B上的内容。脚本里除了直接的删除,增加命令外还有不少控制执行流程的操作,比较复杂,而界面A和B也很复杂,删除和增加都不是容易的事。
上面就是命令模式的类图,Invoker就是命令调度类,Reciever就是执行类,在我们上面的具体应用中,它是界面类,它负责真正的去执行删除和增加界面元素的操作,所以,解耦Invoker和Reciver的任务就成了Command和ConcreteCommand的工作了。我们通过代码示例来理解解耦的过程。
public interface ICommand { /* API */ void execute(); }
这是命令接口,仅仅只有一个执行函数API
public class DeleteCommand implements ICommand { private final Viewer reciever; public DeleteCommand(Viewer viewer) { reciever = viewer; } @Override public void execute() { reciever.delete(); } }
删除界面上元素的命令,这段代码里它仅仅就是个转接调用,在真实的程序里可能包含一些判断,甚至是命令执行相关的Log输出等。
public class AddCommand implements ICommand { private final Viewer reciever; public AddCommand(Viewer viewer) { reciever = viewer; } @Override public void execute() { reciever.add(); } }
添加元素的命令
public class Viewer { public void delete() { /* Delete item from Viewer */ } public void add() { /* add item from Viewer */ } }
界面类,它负责真实的添加和删除
Viewer viewer = new Viewer(); Invoker invoker = new Invoker(); invoker.addCommand(new AddCommand(viewer)); invoker.addCommand(new DeleteCommand(viewer)); invoker.execute();
主程序,除了被保护隔离的viewer和invoker外,其他的代码都是解耦相关的。命令类把自己要执行的界面类给联系起来送到invoker来调度。