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