正在试图模仿一个接口/抽象类在JavaScript不好的做法

我正在编写Node.js中的一些代码,这些代码跳出我的视线,使用战略模式更好地构build。 来自.Net我会创build其他基于的界面,并从那里移动,在JavaScript中这不是很清楚。

我理解为一个典型的语言JavaScript没有接口inheritance的概念,所以我不知道我做了什么是一种气味,因为我似乎无法find引用,除了一个博客文章,试图推断一个接口通过使用强制inheritance类来实现函数的基本抽象类(当它抛出时)。

我的基类

QueryStrategy = function () { }; QueryStrategy.prototype.create = function(){ throw new Error("Not Implemented"); } module.exports = QueryStrategy; 

实施1

 var util = require('util'); var QueryStrategy = require('./queryStrategy'); SelectQueryStrategy = function (query) { this.parameters = query.parameters || []; this.entity = query.entity || ''; }; util.inherits(SelectQueryStrategy, QueryStrategy); SelectQueryStrategy.prototype.create = function () { var self = this, params = self.parameters, paramList = self.parameters.length >= 1 ? '' : '*'; for (var i = 0; i < params.length; i++) { var suffix = i === (params.length - 1) ? '' : ', '; paramList = paramList + params[i].key + suffix; } return util.format("SELECT %s FROM %s", paramList, self.entity); }; module.exports = SelectQueryStrategy; 

目前该基地没有任何共享function或属性。 共享函数会来,属性,因为原型链search我没有看到添加“共享”属性的重点,因为它们被创build的实例(如果这是错误的,让我知道)覆盖。

这是一个可接受的方法,或者我应该忽视在这种情况下的inheritance。 可能有一些types检查,如果你可以推断types为一(即它们都必须是Type QueryStrategytypes),但是我不希望我的.Net偏见在这里接pipe。

替代方法

首先,我不是想在这里卖书,我只是用书本来读这本书,但是我想把它放在应有的地方。

基于这几个评论,说这种types推断在这里没有什么区别,也许应该只是放在Duck Typing来检查,也许试图插入一些没有在语言不是最好的方法。 我已经阅读了关于接口的Addy Osmani Javascript模式,虽然我的实现不尽相同,尽pipe接口的使用是可以接受的,但可能并不需要。

保持策略的方法可能会更简单,但使用不同的实现(Stoyan Stefanov在Javascript Patterns中概述的实现),在那里有一个实现,并且基于某种forms的configuration,您知道使用哪种策略。

伪样品

 QueryBuilder = function () { this.types = []; } QueryBuilder.prototype.create = function (type, query) { var strategy = types[type]; strategy.create(query); }; QueryBuilder.types.Select = { create: function (query) { params = query.parameters, paramList = query.parameters.length >= 1 ? '' : '*'; for (var i = 0; i < params.length; i++) { var suffix = i === (params.length - 1) ? '' : ', '; paramList = paramList + params[i].key + suffix; } return util.format("SELECT %s FROM %s", paramList, query.entity); } }; 

这可能是一个更清洁的方式去,有一点我要注意的是如果我应该添加types的原型,但我想在这种简单的情况下,它不会被需要,但在一个更复杂的情况下,你可以有一个很多策略和一个文件可能需要被抽象出来。

这是一个更可接受的方法?

我结束了

我环顾四周,试图更多地了解鸭子打字,优点和缺点等,并试图根据我收到的一些意见和答案来简化我的devise。 我坚持使用策略方法,因为每个策略都定义了相同的function,基本上封装了各个实现中各不相同的内容,并给他们一个共同的合同,以便find一个更好的术语。

有一点改变的是基类/接口,正如所指出的那样,没有任何build设性的东西被移除,每一个策略都是独立的(所以在模式的经典表示中不是100%),正如所述,只是定义了相同的创build函数。

从嵌套的ifs和switch一次所属的地方被replace为一个单一的switch,根据请求的查询types决定使用哪种查询策略。 这可以在稍后重新考虑到工厂,但现在它的目的是:

 Query.prototype.generate = function () { var self = this, strategy = undefined; switch (this.queryType) { case "SELECT": strategy = new Select(self); break; case "INSERT": strategy = new Insert(self); break; case "UPDATE": strategy = new Update(self); break; case "DELETE": strategy = new Delete(self); break; } return strategy.create(); }; 

每个策略都是独立testing的,我认为这样更容易维护,因为如果有什么失败的话,它会在一个地方失败,根据unit testing调查会更容易。 显然有一个权衡,更多的文件,和一个稍微更复杂的结构…我们将看到会发生什么。

这是一个可以接受的方法,但它不会真的让你受益,并可能使这段代码更难以维护。 策略模式实际上只对静态types的语言有用。 作为另一位评论者提到,你可以看看TypeScript。

在JavaScript中,你将更多地依赖“鸭子打字”……如果它看起来像一只鸭子,闻起来像鸭子,它可能是一只鸭子。

http://en.wikipedia.org/wiki/Duck_typing