• Backend Weekly
  • Posts
  • Part 3: Builder and Prototype Design Patterns (GoF)

Part 3: Builder and Prototype Design Patterns (GoF)

We will explore the Builder and Prototype Design Patterns under the Creational Design Patterns.

Hello “👋

Welcome to another week, another opportunity to become a Great Backend Engineer.

Today’s issue is brought to you by Masteringbackend → A great resource for backend engineers. We offer next-level backend engineering training and exclusive resources.

Before we get started, I have a few announcements:

We recently launched the first modules of three of our courses with a 63% discount for you. Use the coupon code PRESALE at checkout.

Here are what to expect in each course.

  • 10+ in-depth modules

  • 50+ in-depth chapters

  • 160+ high-quality lessons

  • 60+ hours of video training content

Note that the discounted prices are going up every month as we add new modules.

Also, you can pick up a single course from a collection of courses we have on the MB Platform.

Check this out:

🦾 Master AI & ChatGPT for FREE in just 3 hours 🤯

1 Million+ people have attended, and are RAVING about this AI Workshop.
Don’t believe us? Attend it for free and see it for yourself.

Highly Recommended: 🚀

Join this 3-hour Power-Packed Masterclass worth $399 for absolutely free and learn 20+ AI tools to become 10x better & faster at what you do

🗓️ Tomorrow | ⏱️ 10 AM EST

In this Masterclass, you’ll learn how to:

🚀 Do quick excel analysis & make AI-powered PPTs 
🚀 Build your own personal AI assistant to save 10+ hours
🚀 Become an expert at prompting & learn 20+ AI tools
🚀 Research faster & make your life a lot simpler & more…

Now, back to the business of today.

In this series, I will explore Design Patterns, their types, the GoF design patterns, drawbacks, and benefits for backend engineers.

This is coming from my new Vue.js book on “Vue Design Patterns”. However, I’m only transferring the knowledge to backend engineers in this series.

Today, we will explore the Builder and Prototype Design Patterns under the Creational Design Patterns.

Let’s get started quickly.

What are Builder Patterns?

The builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

Here’s a real-world example:

You can use it for creating complex objects like HTTP requests or configurations. Assuming you have an HTTP Request class and you want to be able to chain different operations to the class before building or creating it.

You can achieve that using the builder pattern as shown below:

class Request {
    constructor() {
        this.method = 'GET';
        this.url = '';
        this.headers = {};
        this.body = null;
    }
}

The code snippet above creates a Request class with a default constructor for initializing required properties.

class RequestBuilder {
    constructor() {
        this.request = new Request();
    }

    setMethod(method) {
        this.request.method = method;
        return this;
    }

    setURL(url) {
        this.request.url = url;
        return this;
    }

    setHeaders(headers) {
        this.request.headers = headers;
        return this;
    }

    setBody(body) {
        this.request.body = body;
        return this;
    }

    build() {
        return this.request;
    }
}

In the code snippet above, we created a RequestBuilder class to allow us to add or specify the different configurations we need to add before we create the Request object.

For example, you have different methods to specify different configurations

const request = new RequestBuilder()
    .setMethod('POST')
    .setURL('https://api.example.com/data')
    .setHeaders({ 'Content-Type': 'application/json' })
    .setBody(JSON.stringify({ data: 'example' }))
    .build();

Lastly, in this code snippet, we are using the builder pattern to specify the configuration that we want before creating the Request object using the build method.

With the builder pattern, we can optionally add configurations or remove the ones we don’t want.

The Builder Pattern is useful in software development because it allows for the creation of complex objects step-by-step while hiding the internal details of their construction.

Here is how the builder pattern is useful:

Simplifies Object Construction

When an object has multiple parameters, especially optional or complex ones, constructing it can become cumbersome. The Builder Pattern simplifies this by allowing you to create objects step-by-step, with clear method calls for each configuration option.

Without the Builder Pattern:

class Request {
    constructor(method, url, headers, body) {
        this.method = method;
        this.url = url;
        this.headers = headers;
        this.body = body;
    }
}

const request = new Request('GET', '', {}, null);

From the code snippet above, it can kill readability and maintainability if you ever want to make some parameters optional and if some parameters are longer.

The Builder Pattern is particularly useful in the following scenarios:

  • When an object has multiple parameters, especially when many are optional.

  • When constructing objects is complex and involves multiple steps.

  • When you want to avoid constructor pollution with too many parameters.

  • When immutability or flexibility in object creation is needed.

  • When you want more readable and maintainable code.

What are Prototype Patterns?

The prototype pattern allows you to create new objects by copying an existing object, known as the prototype, rather than creating from scratch.

Here’s a real-world example:

Consider a scenario where creating an object requires a time-consuming process, like retrieving data from a database or running complex computations.

In such situations, using the Prototype pattern to clone an existing object, rather than building a new one from the ground up, can significantly improve efficiency.

You can achieve that using the builder pattern as shown below:

class Database {
    constructor(proto) {
        // Complex database connections and computation
        this.proto = proto;
    }

   // Method to clone the database class
    clone() {
        const clone = Object.create(this.proto);
        clone.connection = this.proto.connection;
        clone.username = this.proto.username;
        clone.password = this.proto.password;
        return clone;
    }
}

// Database properties
const databaseProto = { connection: 'Postegre', username: "root", password:"password" };

//Creating the first instance with all the complex computation
const database = new Database(databaseProto);

// Create a clone for new connection
const databaseClone = database.clone();

The code snippet above is self-explanatory with all the comments. Let me know if you need more clarification.

The Prototype Pattern is useful because it allows you to create new objects by copying or "cloning" existing ones, rather than constructing them from scratch.

This pattern is especially beneficial when the process of creating an object is resource-intensive or when you need to avoid the complexities of using constructors with numerous parameters.

Here's why the Prototype Pattern is useful:

Follows Open/Closed Principle

The Prototype Pattern adheres to the Open/Closed Principle because you can extend or modify object creation without altering the existing class structure.

When you need to create new types of objects or variants, you don’t modify the core logic; instead, you just clone and adjust.

Works Well with Dynamic and Runtime Changes

In some applications, objects may be configured or modified during runtime based on user input, environment, or external factors.

The Prototype Pattern allows you to create a base object and modify it dynamically without needing to know the exact details of how the object was initially constructed.

Example:

A user interface (UI) system where different themes or layouts need to be applied dynamically based on user preferences or system states.

class Theme {
    constructor(color, font, layout) {
        this.color = color;
        this.font = font;
        this.layout = layout;
    }

    clone() {
        return new Theme(this.color, this.font, this.layout);
    }
}

// Base theme
const defaultTheme = new Theme('blue', 'Arial', 'grid');

// Clone and customize for dark mode
const darkModeTheme = defaultTheme.clone();
darkModeTheme.color = 'dark-gray';

console.log(defaultTheme, darkModeTheme);

You can clone an existing configuration and apply modifications without altering the original configuration. The pattern is flexible and adaptable to runtime changes.

The Prototype Pattern is particularly useful in the following scenarios:

  • Performance and efficiency: Cloning is faster and less resource-intensive than creating objects from scratch, especially in scenarios where the object creation process is complex.

  • Reduces code complexity: It simplifies object creation when many parameters or configurations are involved.

  • Supports runtime modifications: Objects can be dynamically cloned and modified based on runtime conditions.

  • Avoids constructor clutter: The need for complex or overloaded constructors is reduced.

  • Handles complex, nested objects: The pattern simplifies the copying of objects with multiple sub-objects.

The Prototype Pattern is a powerful and flexible design pattern that can enhance performance, maintainability, and flexibility in your code, particularly when dealing with objects that require complex construction.

That will be all for today. I like to keep this newsletter short.

Today, I discussed the Builder Pattern and Prototype Pattern, you learned how to implement them, their similarities, and when to use which.

Next week, I will start exploring the Structural Design Patterns.

Don’t miss it. Share with a friend

Did you learn any new things from this newsletter this week? Please reply to this email and let me know. Feedback like this encourages me to keep going.

See you on Next Week.

Remember to start learning backend engineering from our courses:

Top 5 Remote Backend Jobs this week

Here are the top 5 Backend Jobs you can apply to now.

👨‍💻 Binance
✍️ Backend Engineer - Java
📍Remote, Worldwide
💰 Click on Apply for salary details
Click here to Apply for this role.

👨‍💻 Decaf
✍️ Senior Backend Developer
📍Remote, Worldwide
💰 Click on Apply for salary details
Click here to Apply for this role.

👨‍💻 Pinterest
✍️ Backend Software Engineer
📍Remote, Worldwide
💰 Click on Apply for salary details
Click here to Apply for this role.

👨‍💻Sportradar
✍️ Backend Engineer
📍Remote
💰 Click on Apply for salary details
Click here to Apply for this role.

Want more Remote Backend Jobs? Visit GetBackendJobs.com

Backend Engineering Resources

Whenever you're ready

There are 4 ways I can help you become a great backend engineer:

1. The MB Platform: Join 1000+ backend engineers learning backend engineering on the MB platform. Build real-world backend projects, track your learnings and set schedules, learn from expert-vetted courses and roadmaps, and solve backend engineering tasks, exercises, and challenges.

2. The MB Academy:​ The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

3. MB Video-Based Courses: Join 1000+ backend engineers who learn from our meticulously crafted courses designed to empower you with the knowledge and skills you need to excel in backend development.

4. GetBackendJobs: Access 1000+ tailored backend engineering jobs, manage and track all your job applications, create a job streak, and never miss applying. Lastly, you can hire backend engineers anywhere in the world.

LAST WORD 👋 

How am I doing?

I love hearing from readers, and I'm always looking for feedback. How am I doing with The Backend Weekly? Is there anything you'd like to see more or less of? Which aspects of the newsletter do you enjoy the most?

Hit reply and say hello - I'd love to hear from you!

Stay awesome,
Solomon

I moved my newsletter from Substack to Beehiiv, and it's been an amazing journey. Start yours here.

Reply

or to participate.