Customise your burger (Builder Pattern) v3

Customise your burger (Builder Pattern) v3

This article is the 3rd article of the series Design Patterns using Typescript. Please refer to previous articles for continuity

In the midst of everyone loving Mr. Johnson's new menu, his burger spot got super busy with lots of hungry folks. But here's the thing – people wanted more choices for their burgers. So, Mr. Johnson had a cool idea: let customers make their own burgers with whatever they like on them.

The problem

Now, Jack, got on the task. He wanted to let people build their burgers their way. But as he tried to make it happen, he got stuck. It seemed like he had to make a ton of different ways for people to add ingredients to their burgers. And if he wanted to add even more stuff, it looked like he'd have to keep making more and more ways to do it. That's not fun! His Burger class looked like below

export enum Patty {
  "beef" = "beef",
  "chicken" = "chicken",
  "veg" = "veg",
}

export enum Sauce {
  "mayo" = "mayo",
  "mustard" = "mustard",
  tomatoKetcup = "tomatoKetcup",
}

export enum Veggy {
  "onion" = "onion",
  "tomato" = "tomato",
}

export enum Cheese {
  black = "black",
  cheddar = "cheddar",
}
export class BurgerBuilder {
  public ingredients: string[] = ["Cheese"];

  addIngredients(): string[];
  addIngredients(patty: Patty[]): string[];
  addIngredients(patty: Patty[], sauce: Sauce[]): string[];
  addIngredients(patty: Patty[], sauce: Sauce[], veggies: Veggy[]): string[];
  addIngredients(
    patty?: Patty[],
    sauce?: Sauce[],
    veggies?: Veggy[]
  ): string[] {
    if (!patty && !sauce && !veggies) return this.ingredients;
    if (!veggies && !sauce) return this.ingredients.concat(patty || []);
    if (!veggies)
      return this.ingredients.concat(patty || []).concat(sauce || []);
    return this.ingredients
      .concat(patty || [])
      .concat(sauce || [])
      .concat(veggies || []);
  }
}

As evident in the aforementioned class, Jack includes four overloaded methods for addIngredients to accommodate various ways of creating burgers. However, should there be a need to incorporate additional ingredients, further overloaded functions must be appended to fulfil all requirements.

The Solution

Jack seeks guidance from Emma on streamlining the adding of more and more overloading methods. Emma proposes a resolution by implementing the builder pattern to construct the burger, providing a more modular and efficient solution.

Builder Pattern

The Builder Pattern is a creational design pattern used in object-oriented programming. It provides a way to construct a complex object step by step. The main idea behind the Builder Pattern is to separate the construction of a complex object from its representation. This separation allows the same construction process to create different representations of the object.

Emma rewrites the burger class using builder pattern and it looks like below


export enum Patty {
  "beef" = "beef",
  "chicken" = "chicken",
  "veg" = "veg",
}

export enum Sauce {
  "mayo" = "mayo",
  "mustard" = "mustard",
  tomatoKetcup = "tomatoKetcup",
}

export enum Veggy {
  "onion" = "onion",
  "tomato" = "tomato",
}

export enum Cheese {
  black = "black",
  cheddar = "cheddar",
}
export class BurgerBuilder {
  public burger!: string[];
  public ingredients!: string[];
  basicBurger() {
    this.ingredients = ["Cheese"];
    return this;
  }
  addVeggies(veggy: Veggy) {
    this.ingredients.push(veggy);
    return this;
  }
  addCheese(cheese: Cheese) {
    this.ingredients.push(cheese);
    return this;
  }
  addSauce(sauce: Sauce) {
    this.ingredients.push(sauce);
    return this;
  }
  addPatty(patty: Patty) {
    this.ingredients.push(patty);
    return this;
  }
  build() {
    return this.ingredients;
  }
}

Builder class can be called like below and each method can be called as a chain to build the burger.

const burger = new Burger().basicBurger();
burger.addPatty(Patty.beef).addSauce(Sauce.mustard).addCheese(Cheese.cheddar).build()

Jack couldn't contain his excitement as he learned the ropes of the new design pattern. With newfound knowledge, he dove into upgrading the burger app. The customisable burger feature, now powered by the Builder Pattern, took shape beautifully.

His enthusiasm translated into a user-friendly interface, making it a breeze for burger lovers to create their perfect combos. Clicking the deploy button felt like launching a digital celebration as Version 3 of the app went live.

The revamped app, with its sleek design and smooth user experience, was now ready for burger enthusiasts to explore. Jack's journey from learning the design pattern to deploying the upgraded app was a happy ending, promising users a delightful and personalized burger-building adventure.

You can find v3 here Bite Me Burgers

Bite Me Burgers (v3)