建造者模式(Builder Pattern)
Separate the construction of a complex object from its representation so that the same construction process can create different representations
如果一个对象构建过程比较复杂,并且构建部分有些过程是可选的,那么就可以使用建造者模式。建造者模式将复杂对象的构建与其表示(实例)分离,使同样的构建过程可以创建不同的表示(实例)。
概念有点晦涩,简而言之,你要创建一个复杂对象,创建的过程就好像汽车生产流水线一样繁琐,同时这个复杂对象会被不同的地方用到,而且并不是所有属性都用到,也就是说创建对象中间的几个步骤是可选的。对于这种情况,使用建造者模式可以轻松处理。
典型的,在前端中,表单面板一直是一个比较麻烦的东西,在不同的场景下,表单可能会需要不同的输入类型。例如登陆表单需要用户名与密码,而重置密码表单则只需要密码,为这一点差异新做一个表单显然是划不来的。
现在使用TypeScript实现一个使用建造者模式的表单生成器:
1abstract class FormCls {
2 static allItemsType: Exclude<keyof FormCls, "render">;
3
4 username(): string {
5 return `<input name="username" />`;
6 }
7
8 password(): string {
9 return `<input type="password" name="password" />`;
10 }
11
12 email(): string {
13 return `<input type="email" />`;
14 }
15
16 color(): string {
17 return `<input type="color"/>`;
18 }
19
20 date(): string {
21 return `<input type="date"/>`;
22 }
23
24 render(order: (typeof FormCls.allItemsType)[]): string {
25 return order.map(type => this[type]()).join("\n");
26 }
27}
28
29class Form extends FormCls {
30};
31
32abstract class FormBuilderCls {
33 private order: (typeof FormCls.allItemsType)[] = [];
34
35 addItem(item: typeof FormCls.allItemsType) {
36 this.order.push(item);
37 return this;
38 }
39
40 getForm() {
41 const form = new Form();
42 return form.render(this.order);
43 }
44}
45
46class FormBuilder extends FormBuilderCls {
47}
48
49const form = new FormBuilder();
50form.addItem("username").addItem("password");
51
52console.log(form.getForm());
在抽象类FormCls中,定义了几种表单的“零件”,例如用户名、密码、邮件。render
方法接收一个类型为(typeof FormCls.allItemsType)[]
数组,也就是Exclude<keyof FormCls, "render">
,它枚举了FormCls中除了render之外的所有方法。
抽象类FormBuilderCls是一个建造者类,addItem向order添加一个“零件”,调用getForm则返回根据当前order建造的form表单。
从此我们使用表单时,根据所需字段就能建造出符合我们需求的表单。