我正在探索命令模式,并且我试图弄清楚这种模式的实际好处。
我读过以下文章:https://www.safaribooksonline.com/library/view/learning-javascript-design/9781449334840/ch09s08.html
在长时间盯着它之后,我仍然没有看到实施的好处。让我澄清一下我无法得到的东西。
我们有以下命令对象:
(function(){
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.execute = function ( name ) {
return CarManager[name] && CarManager[name].apply( CarManager, [].slice.call(arguments, 1) );
};
文章说这是我们想要实现的目标:
CarManager.execute( "buyVehicle", "Ford Escort", "453543" );
解释是我遇到的问题:
看一下上面的代码,调用我们的代码是微不足道的 通过直接访问对象的CarManager方法。我们都会 原谅我认为这没有任何问题 - 技术上, 它是完全有效的JavaScript。然而,有一些情况 这可能是不利的。
例如,想象一下CarManager背后的核心API是否发生了变化。 这将要求所有对象直接访问这些方法 我们的申请也要修改。这可以被视为一个层 耦合,这有效地违背了OOP的方法论 尽可能松散地耦合物体。相反,我们可以解决 通过进一步抽象API来解决这个问题。
我未能看到的是这个解决方案在任何方面都有益于:
CarManager.buyVehicle("Ford Escort", "453543");
它们是什么意思"如果核心API"变化?我假设他们正在讨论界面,即。命令对象的方法及其实现。但是,如果它们中的任何一个发生变化,它似乎不会改变调用方法的方式(无论是否使用执行,如果方法名称发生变化,两者都不起作用)。
另外,我不知道execute
方法如何解耦任何东西。无论是调用execute
,还是直接执行方法,调用对象都需要引用命令对象。
此外,在文章(参见视觉方案)中,他们提到了客户端,接收器,调用者和命令对象。在示例中,我只看到两个对象(?)。
有人可以开导我吗?
答案 0 :(得分:3)
使用.execute('methodName', ...)
,您可以更改基础方法名称,而不会影响其公共接口。
CarManager.execute('buyVehicle', 'Ford Escort')
实际上可能会调用
this.purchase(car)
引擎盖下。
那就是说,我从来没有在野外见过execute
。但是,您可以在许多jQuery插件中看到这种模式,因为它允许插件只占用fn
命名空间中的一个位置但执行大量命令。前var date = $('#myEl').datepicker('getDate')
答案 1 :(得分:2)
我认为这个解释忽略了这一点。 command pattern用于统一方法调用(" action"),以便您可以通过编程方式处理它们。例如,您可以将命令名称存储在一个数组中,然后在彼此之后执行它们,或者在底层API(execute
函数)中执行它们,您可以将它们记录下来并存储它们以进行重放。
当然,JS已经非常动态了,这并没有太大的改变(你总是可以使用括号表示法按名称执行方法),但是你可以将方法名称作为字符串提供给execute
函数,因此您可以使用它来执行某些操作 - 否则您需要使用ES6代理。
如果API发生变化,使用它的代码当然也需要改变。那个execute
方法甚至可能适得其反,因为不能立即明确字符串参数是需要改变的方法名称(重构工具不会这样),甚至可能不会抛出使用错误的名称调用它时出现异常。
我想这篇文章试图在这里做的一点是,当你已经有了这个命令模式时,外观更容易实现。您可以通过编程方式处理方法名称和参数。
我们假设buyVehicle
方法更改为buyCar
方法。您之前通过
CarManager.buyVehicle = CarManager.buyCar;
你可以使用命令模式插入行
if (name == "buyVehicle")
name = "buyCar";
execute
方法中的。没有太大的优势,但它可能适用于更复杂的案例。
答案 2 :(得分:1)
一些一般性的想法:
1)命令模式允许您定义一个单一的入口点"采取某种行动。
2)构建用户GUI的简洁方法是:收集给定命令所需的所有内容并执行它。从命令结构中创建菜单结构......
3)可以从您想要的任何地方调用此操作。您不必使用特殊类的实例。
4)这是一种非常严格的方式来绑定权利并强制任何行动传递给定路线。
5)此外,这种解耦方法允许您定义宏和某种脚本化过程"。不知道你是否曾经使用过MsAccess。那里的宏编码可以被称为"命令模式"。