Understanding the Builder Design Pattern in Software Development

Akash JayanAkash Jayan
3 min read

Introduction

In software design, the Builder Design Pattern is a creational pattern that allows for the step-by-step construction of complex objects. This pattern is particularly useful when an object requires multiple configurations or when the construction process involves several steps. By separating the construction of a complex object from its representation, the Builder pattern provides a flexible solution for creating different representations of an object.

When to Use the Builder Pattern

  • Complex Object Creation: When an object requires multiple parameters or configurations.

  • Immutable Objects: When you want to create immutable objects with a clear and readable construction process.

  • Fluent Interface: When you want to provide a fluent interface for constructing objects.

Implementing the Builder Pattern in a Next.js.

Let’s implement the Builder Design Pattern in the Next.js. We will create a simple example where we build a user profile object with various attributes.

Step 1: Create the UserProfile Class

First, we will create a UserProfile class that represents the complex object we want to build.

class UserProfile {
    private name: string;
    private email: string;
    private age: number;
    private address: string;

    constructor(builder: UserProfileBuilder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.address = builder.address;
    }

    public static get Builder() {
        return new UserProfileBuilder();
    }

    public toString() {
        return `UserProfile: { Name: ${this.name}, Email: ${this.email}, Age: ${this.age}, Address: ${this.address} }`;
    }
}

class UserProfileBuilder {
    public name: string;
    public email: string;
    public age: number;
    public address: string;

    constructor() {
        this.name = '';
        this.email = '';
        this.age = 0;
        this.address = '';
    }

    public setName(name: string) {
        this.name = name;
        return this;
    }

    public setEmail(email: string) {
        this.email = email;
        return this;
    }

    public setAge(age: number) {
        this.age = age;
        return this;
    }

    public setAddress(address: string) {
        this.address = address;
        return this;
    }

    public build() {
        return new UserProfile(this);
    }
}

export { UserProfile };

Step 2: Use the Builder in a Component

Next, we will use the UserProfile builder in one of our components. For this example, we will modify the AuthContainer to create a user profile after a successful login.

import React from 'react';
import useAuthData from '@/components/auth-provider';
import LoginButton from '@/components/login-button';
import LogoutButton from '@/components/logout-button';
import { UserProfile } from '@/models/UserProfile';

const AuthContainer: React.FC = () => {
    const authData = useAuthData();
    const isAuthenticated = authData?.isAuthenticated;

    const logout = authData?.logout;
    const loginWithEmail = authData?.loginWithEmail;

    const handleLogin = async () => {
        if (loginWithEmail) {
            await loginWithEmail('user@example.com', 'password');
            // Create a user profile after successful login
            const userProfile = UserProfile.Builder
                .setName('John Doe')
                .setEmail('john.doe@example.com')
                .setAge(30)
                .setAddress('123 Main St, Anytown, USA')
                .build();
            console.log(userProfile.toString());
        }
    };

    const handleLogout = logout ? logout : () => console.warn('Logout function is not available');

    return (
        <div>
            {isAuthenticated ? (
                <>
                    <p>Welcome back, user!</p>
                    <LogoutButton onLogout={handleLogout} />
                </>
            ) : (
                <LoginButton onLogin={handleLogin} />
            )}
        </div>
    );
};

export default AuthContainer;

Step 3: Testing the Implementation

Now, when a user logs in, a UserProfile object will be created using the Builder pattern. You can check the console to see the output of the user profile.

Conclusion

The Builder Design Pattern is a powerful tool for constructing complex objects in a clear and manageable way. By implementing this pattern in Next.js , we have demonstrated how to create a user profile with various attributes while maintaining a clean and readable construction process. This pattern not only enhances code readability but also provides flexibility for future modifications.

Final Thoughts

Consider using the Builder Design Pattern in your projects whenever you need to create complex objects. It can significantly improve the maintainability and clarity of your code. Happy coding!

Repo : https://github.com/Akashjayan1999/Design-pattern

0
Subscribe to my newsletter

Read articles from Akash Jayan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Akash Jayan
Akash Jayan