不考虑该设计模式本身的概念,先感受以下两段代码带来的感受先。

  1. class Frog {
  2. constructor(name, weight, height, gender) {
  3. this.name = name
  4. this.weight = weight // in lbs
  5. this.height = height // in inches
  6. this.gender = gender
  7. }
  8. eat(target) {
  9. console.log(`Eating target: ${target.name}`)
  10. }
  11. }
  1. class FrogBuilder {
  2. constructor(name, gender) {
  3. this.name = name
  4. this.gender = gender
  5. }
  6. setWeight(weight) {
  7. this.weight = weight
  8. return this
  9. }
  10. setHeight(height) {
  11. this.height = height
  12. return this
  13. }
  14. build() {
  15. if (!('weight' in this)) {
  16. throw new Error('Weight is missing')
  17. }
  18. if (!('height' in this)) {
  19. throw new Error('Height is missing')
  20. }
  21. return new Frog(this.name, this.weight, this.height, this.gender)
  22. }
  23. }
  24. const leon = new FrogBuilder('Leon', 'male')
  25. .setWeight(14)
  26. .setHeight(3.7)
  27. .build()

由上面的两段代码可以看出,Builder Pattern 主要用来当构建函数传入的参数过于复杂的情况下,进行的代码优化的手段。抽离出不必要的东西,而后在相应的函数中赋予该实例其他的属性。
用 TS 来写

  1. export interface User {
  2. name: string;
  3. age: number;
  4. }
  5. export class UserBuilder {
  6. private readonly _user: User;
  7. constructor() {
  8. this._user = {
  9. name: "",
  10. age: 0
  11. };
  12. }
  13. name(name: string): UserBuilder {
  14. this._user.name = name;
  15. return this;
  16. }
  17. age(age: number): UserBuilder {
  18. this._user.age = age;
  19. return this;
  20. }
  21. build(): User {
  22. return this._user;
  23. }
  24. }
  25. const userWithName: User = new UserBuilder()
  26. .name("John")
  27. .build();
  28. const userWithGender: User = new UserBuilder()
  29. .gender("Female")
  30. .build();

参考资料

  1. The Builder Pattern in JavaScript
  2. Let’s Look at the Builder Pattern in TypeScript