【设计模式】使用 Builder 模式优化参数极多的表单提交方法

2024/04/26 11:03:412023/11/30 22:33:09

什么是 Builder 模式

Builder 模式是一种对象构建模式,主要用于创建复杂的对象。

示例:超过 10 个参数的提交方法

举个栗子:我要封装一个表单提交方法,这个方法长这样:

function submit(name, phone, idCard, age) {}

这样定义的问题是:需要将参数写在固定的位置,随着参数的增多,这种传参方式会变得难以维护。

在参数变得更多时,要确认某一个参数是什么含义就会变得相当困难,如果某些参数还是非必填项,就会更难理解:

submit(
  this.numberDetailsInfo.number,
  this.currentSubCharge,
  "000001",
  this.orderParam.certName,
  this.orderParam.certNo,
  this.orderParam.contactNum,
  [
    this.orderParam.deliveryProvinceName,
    this.orderParam.deliveryCityName,
    this.orderParam.deliveryDistrictName,
  ],
  this.orderParam.address,
  "",
  openId,
  "",
  true,
  false
);

可以将所有参数合并到一个对象中传递,但是这样的缺点是必须查看文档或者到方法的源码中才能知道这个方法具体需要什么参数:

function submit(params) {
  const name = params.name;
  const phone = params.phone;
  // ...
}

可以看到无论是哪种方式,随着参数增多,上面的两种封装方式都会让代码变得难以理解,对于使用者来说很不友好。

使用 Builder 模式优化

Builder 模式改造的思路是:不直接调用 submit() 函数,而是提供一个生成器对象来辅助调用。

生成器对象为每个 submit() 方法的参数提供 set() 方法。

生成器对象提供一个 invoke() 方法,在执行时调用 submit() 方法。

// 将参数合并到一个对象中
function submit(params) {
    const name = params.name
    const phone = params.phone
    // ...
}

// 表单提交辅助类
class SubmitBuilder() {
    name // 名称
    phone // 手机号
    setIdCard // 身份证号

    get age() {
        if(this.idCard) {
            // 从身份证号中提取
        }
        return ''
    }
    // ...
    setName(name) {
        this.name = name
    }

    setPhone(phone) {
        this.phone = phone
    }

    setIdCard(idCard) {
        this.idCard = idCard
    }

    invoke() {
        submit({
            name: this.name,
            phone: this.phone,
            age: this.age
            // ...
        })
    }
}

使用生成器对象完成提交表单操作:

// 构建提交对象
const submitBuilder = new SubmitBuilder();

// 填充参数
submitBuilder.setName("zkb").setPhone("188");

// 提交
submitBuilder.invoke();

可以看到,Builder 模式让代码变得比原来清晰许多,这样做有这些好处:

  • 让开发者不用直接去调用复杂的方法,而是可以在辅助类的引导下一步一步填充参数,更加简单易用。
  • 如果参数之间有联动关系,可以在 set() 方法中去操作。
  • 如果一个参数可以由另一个参数推导出来,可以用 getter 来定义前者。
  • 添加参数时易于扩展、维护。

总结

从上面的例子可以看出,Builder 模式并没有解决参数过多造成函数难以维护的问题。

submit() 函数本身还是难以维护的,但是好在我们现在只需要在 SubmitBuilderinvoke() 方法中去维护它。

参考

《Node.js 设计模式》