Design Patterns in PHP 8: Builder

Max Zhuk - Jul 15 '23 - - Dev Community

Hello, fellow developers!πŸ§‘πŸΌβ€πŸ’»

In the realm of software development, creating complex objects often feels like trying to solve a Rubik's cube. It's a step-by-step process, where every move is crucial and affects the final outcome. But what if we had a guide, a blueprint that could help us solve this puzzle effortlessly? In the world of programming, the Builder pattern serves as this guide.

The Builder pattern, a member of the esteemed creational design patterns family, is like a master craftsman in the world of object-oriented programming. It knows the intricacies of creating multifaceted objects, handling the construction process with finesse and precision. The beauty of the Builder pattern lies in its ability to construct diverse representations of an object, all while keeping the construction logic shielded from the client code.

In this article, we'll embark on a journey to explore the Builder pattern, unraveling its capabilities with PHP 8. We'll delve into its structure, understand its nuances, and see it in action with real-world examples. Whether you're building an intricate e-commerce platform or a simple blog, the Builder pattern can be your secret weapon to handle complex object creation with ease and elegance.

Imagine you're building an e-commerce application where you have a Product class. The Product class has many details like id, name, price, description, manufacturer, inventory, discount, etc.

Creating a Product object is a multi-step and sequential process. If we create multiple constructors for each attribute, it will lead to a large number of constructor parameters. This is known as the telescoping constructor anti-pattern.

class Product
{
    public int $id;
    public string $name;
    public int $price;
    public string $description;
    public string $manufacturer;
    public string $inventory;
    public int $discount;

    public function __construct(
      int $id,
      string $name,
      int $price,
      string $description,
      string $manufacturer,
      string $inventory,
      int $discount
    )
    {
        $this->id = $id;
        $this->name = $name;
        $this->price = $price;
        $this->description = $description;
        $this->manufacturer = $manufacturer;
        $this->inventory = $inventory;
        $this->discount = $discount;
    }
}
Enter fullscreen mode Exit fullscreen mode

The Builder pattern can solve this problem.

class Product
{
    private $id;
    private $name;
    private $price;
    private $description;
    private $manufacturer;
    private $inventory;
    private $discount;

    public function __construct(ProductBuilder $builder)
    {
        $this->id = $builder->getId();
        $this->name = $builder->getName();
        $this->price = $builder->getPrice();
        $this->description = $builder->getDescription();
        $this->manufacturer = $builder->getManufacturer();
        $this->inventory = $builder->getInventory();
        $this->discount = $builder->getDiscount();
    }

    // getters for product details will go here
}

class ProductBuilder
{
    private $id;
    private $name;
    private $price;
    private $description;
    private $manufacturer;
    private $inventory;
    private $discount;

    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    public function setPrice($price)
    {
        $this->price = $price;
        return $this;
    }

    public function setDescription($description)
    {
        $this->description = $description;
        return $this;
    }

    public function setManufacturer($manufacturer)
    {
        $this->manufacturer = $manufacturer;
        return $this;
    }

    public function setInventory($inventory)
    {
        $this->inventory = $inventory;
        return $this;
    }

    public function setDiscount($discount)
    {
        $this->discount = $discount;
        return $this;
    }

    // getters will go here

    public function build()
    {
        return new Product($this);
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the ProductBuilder class is responsible for step-by-step construction of the Product object. The Product class itself has a constructor with a ProductBuilder argument. This way, we ensure that a product object is always created in a complete state.

$productBuilder = new ProductBuilder();
$product = $productBuilder
                ->setId(101)
                ->setName('iPhone 13')
                ->setPrice(999.99)
                ->setDescription('New iPhone 13 with A15 Bionic chip')
                ->setManufacturer('Apple Inc.')
                ->setInventory(1000)
                ->setDiscount(10)
                ->build();
Enter fullscreen mode Exit fullscreen mode

As we reach the end of our exploration of the Builder pattern, it's clear to see why it's considered a cornerstone in the world of object-oriented programming. The Builder pattern elegantly solves the problem of constructing complex objects, reducing the intricacy and enhancing the readability of our code.

One of the standout features of the Builder pattern is its ability to separate the construction and representation of an object. This separation not only makes our code more modular but also improves its maintainability and scalability. It's like having a personal architect who understands our vision and brings it to life, one brick (or in our case, one object) at a time.

On a personal note, the Builder pattern holds a special place in my toolbox of design patterns. Over the years, it has proven to be an invaluable ally, helping me construct complex objects in my projects with ease and precision. Its versatility and robustness make it my go-to pattern when dealing with intricate object creation. It's like a trusted friend who never lets me down, no matter how complex the task at hand.


P.S. Fellow developers, if you've found value in this article and are eager to deepen your understanding of design patterns in PHP and TypeScript, I have thrilling news for you! I am in the midst of crafting a comprehensive book that delves extensively into these topics, filled with practical examples, lucid explanations, and real-world applications of these patterns.

This book is being designed to cater to both novices and seasoned developers, aiming to bolster your understanding and implementation of design patterns in PHP and TypeScript. Whether you are aiming to refresh your existing knowledge or venture into new learning territories, this book is your perfect companion.

Moreover, your subscription will play a pivotal role in supporting the completion of this book, enabling me to continue providing you with quality content that can elevate your coding prowess to unprecedented heights.

I invite you to subscribe to my blog on dev.to for regular updates. I am eager to embark on this journey with you, helping you to escalate your coding skills to the next level!


Photo by Ravi Avaala on Unsplash

. . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player