javascript - 这是策略模式吗
问题描述
为了从一个 http 客户端移动到另一个(相同的概念可以应用于日志库、数据库),我实现了这个解决方案,但我不确定它是否是 OOP 世界中的一种模式。在看了一些之后,它看起来有点像策略模式或存储库模式。但是我从存储库模式中了解到,它仅限于数据访问功能。然而,同样的概念可以应用于日志库、http 客户端或电子邮件客户端等。
这是我不知道名称的实现:( =D )
const fetch = require('node-fetch');
const axios = require('axios');
class MyHttpAxios {
constructor(axios) {
this.axios = axios;
}
async get(url) {
const response = await this.axios.get(url);
return response.data;
}
}
class MyHttpFetch {
constructor(fetch) {
this.fetch = fetch;
}
async get(url) {
const response = await this.fetch(url);
return response.json();
}
}
const httpClients = {
axios: new MyHttpAxios(axios),
fetch: new MyHttpFetch(fetch),
};
const client = httpClients['axios'];
client
.get('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response)
.then(json => console.log(json));
解决方案
在回答之前我想说的是,Strategy模式及其派生的思想就是利用dynamic dispatch
and这种方式来代替手动管理条件逻辑在代码中进行行为参数化,留下多态/条件行为的选择到运行时。IMO 策略模式是多态的最基本和最实用的形式。动态类型语言使用鸭子类型来做到这一点,但想法是一样的。
您在这里使用了某种策略模式,利用了我需要添加的鸭子类型,因为typescript
问题中有一个标签(实际上,使用 ES6 添加的 typescript 和 class 关键字不会改变 javascript 的性质是一种使用 protoypal 继承的语言,但是如果我们用这种语法糖来考虑 GoF,我需要添加这个)。
我在这里看到了一些问题。第一个是是否值得付出努力,因为您可以直接使用axios.get(url).then(...)
,或者fetch(url).then(...)
我的意思是在这种情况下没有真正的多态行为,这里的变化或条件行为只是 http 客户端和次要方法(httpClient.get/x/y/z().then() to httpClient.url().then()
)以及来自如果您的代码仅保留单个方法,则此观点也看起来像 a command pattern
,这意味着仅使用 lambda 函数。但是,如果您的目的是创建一个库,并且您的具体类将成为 http 客户端多个方法之上的包装器,然后为用户提供选择,那么它会更好。所以你的混凝土将是包装材料。
一些 GoF 方法实际上是包装器,它们的区别在于它们的intent
s ,实际上 aFacade
在这里就足够了。
使用经典继承和静态类型,使用策略/策略模式的想法可能如下:
客户端/驱动程序类是:
class Client {
fetchPolicy = PolicyFactory.getFetchPolicy('axios');
data = new Fetcher().fetchSomeData(fetchPolicy, 'https://jsonplaceholder.typicode.com/todos/1');
}
选择具体实现的基本工厂类:
class PolicyFactory {
const httpClients = {
axios: new MyHttpAxios(),
fetch: new MyHttpFetch(),
};
public static getFetchPolicy(policyType: string): FetchPolicy {
return Object.keys(httpClients).find(key => key === policyType);
}
}
这实际上是不必要的,只是httpClients['axios'] with httpClients object/map
在上面使用。
参数化行为:
interface FetchPolicy {
get(url: string): any;
}
class MyHttpAxios implements FetchPolicy {
async get(url) {
const response = await this.axiosGet(url);
return response.data;
}
private axiosGet(url) {
axios // Since it is global use directly, or if you don't pass as a parameter in the client
.get(url)
.then(response => response)
.then(json => console.log(json));
}
}
class MyHttpFetch implements FetchPolicy {
async get(url) {
const response = await this.fetch(url).then(/*...*/);
return response.json();
}
}
这也与您的代码大致相似。
虽然这么说你可以只使用 lambdas 来提供这种抽象:
const fetch = require('node-fetch');
const axios = require('axios');
((url, httpClientFn, transformFn) => {
return httpClientFn(url).then(response => transformFn(response))
})("http://...", url => axios.get(url), response => console.log(response));
//somewhere in other clients which use the fetch
((url, httpClientFn, transformFn) => {
return httpClientFn(url).then(response => transformFn(response))
})("http://...", url => fetch.url(url), response => console.log(response));
推荐阅读
- admin - 无极科技VTrak配置网络服务器
- javascript - Paper JS only exporting
- reactjs - 如何将 React 16.3 上下文提供程序与 redux 存储一起使用?
- regex - Notepad ++ regex expression to put quotes around the contents of square brackets
- sql - 验证 SSIS 中的文件结构
- python - Pygame Text:让文本显示图像或动画,而不是颜色
- mysql - mySQL 左连接 5 个表?
- php - 通过 PHP 从 Wordpress 访问 LinkedIn 上公司的股票
- java - 可以用任何类型 T 创建泛型类的对象吗?
- javascript - 如何从 JavaScript 访问 Kotlin 对象