gpt4 book ai didi

javascript - 试图在 javascript 不良实践中模仿接口(interface)/抽象类

转载 作者:IT老高 更新时间:2023-10-28 23:08:26 29 4
gpt4 key购买 nike

我正在用 Node.js 编写一些代码,这些代码让我觉得使用策略模式结构更好。来自 .Net 我将创建其余部分所基于的接口(interface)并从那里移动,在 JavaScript 中这不是那么明确。

我理解作为一种原型(prototype)语言 JavaScript 没有接口(interface)继承的概念,所以我不确定我所做的是否是一种气味,因为我似乎找不到引用,除了一篇试图推断接口(interface)的博客文章通过使用一个基抽象类来强制继承类实现该函数(当它抛出时)。

我的基类

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;

目前,该基础没有任何共享功能或属性。共享功能将出现,属性,因为原型(prototype)链搜索我没有看到添加“共享”属性的意义,因为它们被创建的实例覆盖(如果这是错误的,请告诉我)。

这是一种可接受的方法,还是在这种情况下我应该忽略继承。可能会有一些类型检查,如果您可以将类型推断为一个(即它们都必须是 Type QueryStrategy),那么它会更容易,但我不希望我的 .Net 偏见在这里接管。

替代方法

首先,我不是想在这里卖书,我只是用我拥有的书阅读了很多关于这个主题的书,但想在应得的地方给予赞扬。

根据这几条评论,可以正确地说类型推断在这里不会有任何区别,可能应该留给 Duck Typing 来检查,并且可能试图插入一些未在语言不是最好的方法。我已经阅读了关于接口(interface)的 Addy Osmani Javascript 模式,虽然我的实现不一样,虽然接口(interface)使用是可以接受的,但可能不需要。

保留策略方法可能更简单,但使用不同的实现,在 Stoyan Stefanov 的 Javascript 模式中概述的一种实现,您有一个实现,并且基于某种形式的配置,您知道要使用哪种策略。

伪样本
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);
}
};

这可能是一种更简洁的方法,我要确定的一件事是我是否应该向原型(prototype)添加类型,但我想在这种简单的情况下不需要它,但在更复杂的情况下,你可以有一个许多策略和一个文件可能需要抽象出来。

这是一种更容易接受的方法吗?

我最终得到了

我环顾四周,试图了解更多关于 Duck 打字、优点和缺点等的信息,并尝试根据收到的一些评论和回答来简化我的设计。我坚持采用类似策略的方法,因为每个策略都定义了相同的功能,本质上封装了实现中的不同之处,并为它们提供了一个通用的契约(Contract),以便获得更好的条款。

改变的一件事是基类/接口(interface),正如正确指出的那样,它没有做任何 build 性的事情被删除了,每个策略都是独立的(因此在模式的经典表示中不是 100%)它们,如前所述,它们只是定义相同的创建函数.

从嵌套的 if 和 switch 曾经所属的地方开始,已被单个 switch 替换,该 switch 根据请求的查询类型决定使用哪种查询策略。稍后可以将其重新分解为工厂,但现在它达到了它的目的:
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();
};

每个策略都经过独立测试,我觉得这更容易维护,就好像某事失败了,它会在一个地方失败,并且基于单元测试的调查会更容易。显然有一个权衡,更多的文件,和一个稍微复杂的结构......我们将看看会发生什么。

最佳答案

这是一种可以接受的方法,但它不会以任何方式真正使您受益,并且可能会使这段代码更难以维护。策略模式实际上只对具有静态类型的语言有用。正如另一位评论者提到的,您可以查看 TypeScript。

在 JavaScript 中,您将更多地依赖“Duck Typing”……如果它看起来像鸭子,闻起来像鸭子,那么它可能就是一只鸭子。

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

关于javascript - 试图在 javascript 不良实践中模仿接口(interface)/抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13139685/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com