频道栏目
首页 > 程序开发 > 软件开发 > 其他 > 正文
设计模式(七):命令模式
2016-06-29 09:27:24         来源:海角在眼前  
收藏   我要投稿

这个模式我在书上(JavaScript设计模式)的那个章节来来回回看了几遍,有两个关键点并没有说清楚,导致尽管表面上是很简单明了,但本质没有说清,以下是书上的例子。

书中淡解

例子(改前):

var carManager = {
     // request information
     requestInfo: function( model, id ){
       return "The information for " + model + " with ID " + id + " is foobar";
     },
     // purchase the car
     buyVehicle: function( model, id ){
       return "You have successfully purchased Item " + id + ", a " + model;
     },
     // arrange a viewing
     arrangeViewing: function( model, id ){
       return "You have successfully booked a viewing of " + model + " ( " + id + " ) ";
     }
};
carManager.arrangeViewing("Ferrari", "14523" );
carManager.requestInfo("Ford Mondeo", "54323" );
carManager.requestInfo("Ford Escort", "34232" );
carManager.buyVehicle("Ford Escort", "34232" );

例子(改后,命名模式):

carManager.execute = function ( name ) {
    return carManager[name] && carManager[name].apply( carManager, [].slice.call(arguments, 1) );
};
 
carManager.execute( "arrangeViewing", "Ferrari", "14523" );
carManager.execute( "requestInfo", "Ford Mondeo", "54323" );
carManager.execute( "requestInfo", "Ford Escort", "34232" );
carManager.execute( "buyVehicle", "Ford Escort", "34232" );

我想不明白,凭什么加上这个方法,就得到了优化,哪里就解耦了。

当carManager的API改变时候,调用这些API的对象当然都需要做修改,无论是改前、或者改后的代码写法。

PS:所以感觉例子不当。

网上见解

我带着疑问,放下书本,在网上寻找资料。我发现JavaScript实现的命令模式,都是类似上面的,而其他面向对象语言的实现,就是正正经经的按照模式的类图(如下)。于是,我就奇怪了,为什么JavaScript和面向对象的例子区别这么大,按理说模式应该与实现语言无关,特别是理论部分,更没有说到一块去(大部分)。

\

\

客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。

命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。

具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。

请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。

接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。

例子:

public interface Command {
    public void execute();
}
 
public class ConcreteCommand implements Command {
 
    private Receiver receiver = null;
    private String state;
 
    public ConcreteCommand(Receiver receiver){
      this.receiver = receiver;
    }
    public void execute() {
      receiver.action();
    }
}
 
public class Receiver {
    public void action(){
      //真正执行命令操作的功能代码
    }
}
 
public class Invoker {
    private Command command = null;
 
    public void setCommand(Command command) {
      this.command = command;
    }
 
    public void runCommand() {
      command.execute();
    }
}
 
public class Client {
    public void assemble(){
      //创建接收者
      Receiver receiver = new Receiver();
      //创建命令对象,设定它的接收者
      Command command = new ConcreteCommand(receiver);
      //创建Invoker,把命令对象设置进去
      Invoker invoker = new Invoker();
      invoker.setCommand(command);
    }
}

我的见解

首先命令(Command)模式是行为设计模式。

定义:

命令模式是将方法调用、请求或操作(Receiver类里的方法)封装到一个中间者(command类),供调用者(Invoker)调用。调用者不需要知道接收者的任何接口。

例子:

Command模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单选择一个命令时,然后会执行一些动作。

将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式。换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了。

简而言之,本来是调用者直接调接收者代码的,不过Command模式在两者间加了一层中间者,中间者封装接收者动作,调用者直接调中间者。

使用场景:

1.图形界面的菜单命令。

2. 需要支持命令的撤消(undo)。

优点:

1.解耦了发送者和接受者之间联系。发送者调用一个操作,接受者接受请求执行相应的动作,因为使用Command模式解耦,发送者无需知道接受者任何接口。

2.它能实现Undo功能。每个具体命令都可以记住它刚刚执行的动作,并且在需要时恢复。

缺点:

滥用设计模式的带来的弊端而已。

 

总结

在仔细查阅资料后,关于上面面向对象语言和JavaScript的各自实现例子,我认为面向对象语言是更为准确,而JavaScript是不恰当的。JavaScript的例子根本没有做到接收者与调用者的解耦,虽然carManager.execute看起来像中间者,但调用者需要知道接收者里面的接口,这里是耦合了。所以,JavaScript实例看看就算了,并不正确

另外有篇文中讲的,设计模式一个"通病":好象喜欢将简单的问题复杂化,喜欢在不同类中增加第三者,当然这样做有利于代码的健壮性、可维护性、还有复用性。这一点也有同感。

 

点击复制链接 与好友分享!回本站首页
上一篇:泛型编程
下一篇:ES6和ES5中数据结构的遍历
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站