Z

建造者模式(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表单。

从此我们使用表单时,根据所需字段就能建造出符合我们需求的表单。