工厂函数

工厂函数,通常是指固定返回特定实例的函数。

一般来说,工厂函数的用法有以下几种。

类的构造函数的参数很多

这种情况比较常出现在调用第三方库时,或者调用自己写的一些比较通用的库的时候(通用很多时候就代表可配置性强),往往在项目中只有少数几个参数需要变动,如果每个地方都写一长串的初始化的话就会显得很冗长。

比如说:

import library

def factory(param1, param2) -> library.Class:
    return library.Class(
        param1=param1,
        param2=param2,
        fixed_param1=...,
        fixed_param2=...,
        fixed_param3=...,
        fixed_param4=...,
        fixed_param5=...,
        # more fixed parameter
    )

一个比较实际的例子:

function rubyFactory(text: string, notation?: string): string {
  if (notation === undefined) {
    return `<span>${text}</span>`
  }
  return `
    <ruby data-notation="${notation}">${text}
      <rp>(</rp>
      <rt>${notation}</rt>
      <rp>)</rp>
    </ruby>
  `
}

类实例化后有固定的初始化操作

比如说这里对于 SourceNode 的初始化,由于 SourceNode 创建之后要做一些固定的属性设置,将其封装到一个工厂函数能显著提高代码的内聚程度。

class AudioPlayer {
    // ...
    sourceNodeFactory(buffer: typeof NodeAudioBuffer, loop: boolean) {
        const source: any =
            this.#audioContext.createBufferSource() // This is the constructor of SourceNode

        if (this.#sourceNode) {
            source.onended = this.#sourceNode.onended
        }
        source.buffer = buffer
        source.loop   = loop
        source.connect(this.#gainNode)
    
        this.#sourceNode = source
        return source
    }
    // ...
}

进行抽象

这种情况和第一种情况很像,不过更偏向于增强代码的可读性,而不是方便书写。

比如:

const callbackNameFactory = () => crypto.randomUUID()

一个类组合另一个类,但是不能让两个类过于耦合

class InnerClass:
    def __init__(self, param):
        pass

class OuterClass:
    def __init__(self, inner_instance: InnerClass, param):
        self._inner = inner_instance

def outer_factory(param1, param2) -> OuterClass:
    inner = InnerClass(param1)
    outer = OuterClass(inner, param2)

点此查看原文