Command 模式是最让我疑惑的一个模式我在阅读了很多代码后才感觉隐约掌握其大概原理我认为理解设计模式最主要是掌握起原理构造这样才对自己实际编程有指导作用Command 模式实际上不是个很具体规定很多的模式正是这个灵活性让人有些confuse
Command 定义
不少Command 模式的代码都是针对图形界面的它实际就是菜单命令我们在一个下拉菜单选择一个命令时然后会执行一些动作
将这些命令封装成在一个类中然后用户(调用者)再对这个类进行操作这就是Command 模式换句话说本来用户(调用者)是直接调用这些命令的如菜单上打开文档(调用者)就直接指向打开文档的代码使用Command 模式就是在这两者之间增加一个中间者将这种直接关系拗断同时两者之间都隔离基本没有关系了
显然这样做的好处是符合封装的特性降低耦合度Command 是将对行为进行封装的典型模式Factory 是将创建进行封装的模式从Command 模式我也发现设计模式一个通病:好象喜欢将简单的问题复杂化 喜欢在不同类中增加第三者当然这样做有利于代码的健壮性 可维护性 还有复用性
如何使用?
具体的Command 模式代码各式各样因为如何封装命令不同系统有不同的做法下面事例是将命令封装在一个Collection 的List 中任何对象一旦加入List 中实际上装入了一个封闭的黑盒中对象的特性消失了只有取出时才有可能模糊的分辨出:
典型的Command 模式需要有一个接口接口中有一个统一的方法这就是将命令/请求封装为对象:
public interface Command {
public abstract void execute ( );
}
具体不同命令/请求代码是实现接口Command下面有三个具体命令
public class Engineer implements Command {
public void execute( ) {
//do Engineers command
}
}
public class Programmer implements Command {
public void execute( ) {
//do programmers command
}
}
public class Politician implements Command {
public void execute( ) {
//do Politicians command
}
}
按照通常做法我们就可以直接调用这三个Command但是使用Command 模式我们要将他们封装起来扔到黑盒子List 里去:
public class producer{
public static List produceRequests() {
List queue = new ArrayList();
queueadd( new DomesticEngineer() );
queueadd( new Politician() );
queueadd( new Programmer() );
return queue;
}
}
这三个命令进入List 中后已经失去了其外表特征以后再取出也可能无法分辨出谁是Engineer 谁是Programmer 了看下面如何调用Command 模式:
public class TestCommand {
public static void main(String[] args) {
List queue = ProducerproduceRequests();
for (Iterator it = erator(); ithasNext(); )
//取出List 中东东其他特征都不能确定只能保证一
个特征是%正确
// 他们至少是接口Command 的儿子所以强制转换
类型为接口Command
((Command)itnext())execute();
}
}
由此可见调用者基本只和接口打交道不合具体实现交互这也体现了一个原则面向接口编程这样以后增加第四个具体命令时就不必修改调用者TestCommand 中的代码了
理解了上面的代码的核心原理在使用中就应该各人有自己方法了特别是在如何分离调用者和具体命令上有很多实现方法上面的代码是使用从List 过一遍的做法这种做法只是为了演示
使用Command 模式的一个好理由还因为它能实现Undo 功能每个具体命令都可以记住它刚刚执行的动作并且在需要时恢复
Command 模式在界面设计中应用广泛Java 的Swing 中菜单命令都是使用Command 模式由于Java 在界面设计的性能上还有欠缺因此界面设计具体代码我们就不讨论网络上有很多这样的示例