JS/TS: 我怎样才能把一个工厂函数变成一个更实用的模式?
JS/TS: How can I turn a factory function into a more functional pattern?
我已将 class 重构到一个模块中,其中每个函数都需要辅助函数才能工作。
OO Class
class Foo {
constructor(config) {
this.helper = new Helper(config);
}
fooMethod (arg) {
return this.helper(arg);
}
}
工厂方法
const fooFN = (helper) => (arg) => helper(arg);
export default Foo (config) => {
const helper = new Helper(config);
return {
fooMethod: fooFN(helper)
}
}
这个辅助函数是在工厂函数中初始化的,returns所有需要辅助方法的函数的一部分。
IMO 这不是路的尽头。与 class 的区别很小,可能还有另一种更实用的方法来编写它,但我无法理解它。
如何将辅助函数传递给模块的每个导出成员,而无需在每次调用成员时都初始化辅助函数?
考虑您的面向对象代码。
class Foo {
constructor(config) {
this.helper = new Helper(config);
}
fooMethod (arg) {
return this.helper(arg);
}
}
以下是我将其重构为函数式风格的方法。
const Foo = helper => ({ helper }); // constructor
const fooFunction = (foo, arg) => foo.helper(arg); // fooMethod
您将按如下方式使用它。
const foo = Foo(Helper(config)); // new Foo(config)
fooFunction(foo, arg); // foo.fooMethod(arg);
如您所见,代码更加简洁。此外,它更简单,因为您不使用 this
或 new
.
编辑: 如果您担心导入太多东西,那么您可以使用命名空间导入。
import { Helper } from "./helper";
export const Foo = helper => ({ helper }); // data constructor
export const Foo2 = config => Foo(Helper(config)); // constructor
export const fooFunction = (foo, arg) => foo.helper(arg); // fooMethod
您将按如下方式使用它。
import * as F from "./foo";
const foo = F.Foo2(config); // new Foo(config)
F.fooFunction(foo, arg); // foo.fooMethod(arg);
引用 Zen of Python,“命名空间是一个很棒的想法——让我们做更多!”
我看不出有什么理由要从您的对象中删除 .helper
属性。你可以只写
function fooMethod(arg) {
return this.helper(arg);
}
export default function(config) {
return {
helper: Helper(config),
fooMethod,
}
}
这样 fooMethod
被重用,就像 class
语法一样。
我宁愿利用组合并完全避免任何 class。
- 它不一定是 class,因为它实际上并不依赖于任何内部状态或上下文。
- 我们知道
fn
除非提供 helper
依赖项,否则无法使用。
function Helper(config) {
return (...args) => console.log({ config, args });
}
const withHelper = (helper) => (...args) => helper(...args);
const foo = withHelper(new Helper({ name: 'foo' }));
const baz = withHelper(new Helper({ name: 'baz' }));
foo(1, 2, 3, 4);
baz('Hello', 'World');
我已将 class 重构到一个模块中,其中每个函数都需要辅助函数才能工作。
OO Class
class Foo {
constructor(config) {
this.helper = new Helper(config);
}
fooMethod (arg) {
return this.helper(arg);
}
}
工厂方法
const fooFN = (helper) => (arg) => helper(arg);
export default Foo (config) => {
const helper = new Helper(config);
return {
fooMethod: fooFN(helper)
}
}
这个辅助函数是在工厂函数中初始化的,returns所有需要辅助方法的函数的一部分。
IMO 这不是路的尽头。与 class 的区别很小,可能还有另一种更实用的方法来编写它,但我无法理解它。
如何将辅助函数传递给模块的每个导出成员,而无需在每次调用成员时都初始化辅助函数?
考虑您的面向对象代码。
class Foo {
constructor(config) {
this.helper = new Helper(config);
}
fooMethod (arg) {
return this.helper(arg);
}
}
以下是我将其重构为函数式风格的方法。
const Foo = helper => ({ helper }); // constructor
const fooFunction = (foo, arg) => foo.helper(arg); // fooMethod
您将按如下方式使用它。
const foo = Foo(Helper(config)); // new Foo(config)
fooFunction(foo, arg); // foo.fooMethod(arg);
如您所见,代码更加简洁。此外,它更简单,因为您不使用 this
或 new
.
编辑: 如果您担心导入太多东西,那么您可以使用命名空间导入。
import { Helper } from "./helper";
export const Foo = helper => ({ helper }); // data constructor
export const Foo2 = config => Foo(Helper(config)); // constructor
export const fooFunction = (foo, arg) => foo.helper(arg); // fooMethod
您将按如下方式使用它。
import * as F from "./foo";
const foo = F.Foo2(config); // new Foo(config)
F.fooFunction(foo, arg); // foo.fooMethod(arg);
引用 Zen of Python,“命名空间是一个很棒的想法——让我们做更多!”
我看不出有什么理由要从您的对象中删除 .helper
属性。你可以只写
function fooMethod(arg) {
return this.helper(arg);
}
export default function(config) {
return {
helper: Helper(config),
fooMethod,
}
}
这样 fooMethod
被重用,就像 class
语法一样。
我宁愿利用组合并完全避免任何 class。
- 它不一定是 class,因为它实际上并不依赖于任何内部状态或上下文。
- 我们知道
fn
除非提供helper
依赖项,否则无法使用。
function Helper(config) {
return (...args) => console.log({ config, args });
}
const withHelper = (helper) => (...args) => helper(...args);
const foo = withHelper(new Helper({ name: 'foo' }));
const baz = withHelper(new Helper({ name: 'baz' }));
foo(1, 2, 3, 4);
baz('Hello', 'World');