This is the fifth post of the Design Pattern series and in this blog post, we will discuss the Builder Design Pattern and its implementation in C# programming language. The Builder Design Pattern is used to create an object and falls into the Creational Pattern category as defined by the Gang of Four (GoF). If you are new to design patterns, I would highly recommend you to read the introductory post “Introduction to Design Patterns“
What is the Builder Design Pattern
The Builder Pattern is a creational design pattern and is used to build an object in a step by step manner and assembling the output of each step to get the final object instance. The pattern is commonly used to build complex objects.
As per the GoF, the Builder pattern is defined as “Separate the construction of a complex object from its representation so that the same construction process can create different representations“. In simple words, the Builder pattern describes the process to separate an object from its construction and the same process can be used to create different objects.
When to consider the Builder Pattern
When you want to avoid constructor nesting, having multiple constructors to support different parameters. Instead, add a new method in the builder interface with the desired parameters, and the job is done without overloading the constructors with a huge parameters list. This introduces cleaner code and easy maintenance.
Builder Pattern UML
The classes participating in this pattern are as follows:
- Builder: This is an abstract interface for creating parts of the Product object.
- ConcreteBuilder: This is the concrete builder class that constructs and assembles the parts of the Product. This class implements the Builder class and also keeps the track of the representation that it creates. The class also provides an interface to retrieve the Product object.
- Director: This is the class that uses the service of the Builder class to construct the Product object.
- Product: This is the class that represents the complex object that is to be constructed.
Advantages of the Builder Pattern
- The object can be constructed in the step by step manner and the construction steps can be deferred or executed in a recursive manner if required.
- The code becomes simple, easy to understand and is more maintainable.
- The same construction code can be used to create various representations of the object.
Disadvantages of the Builder Pattern
- The code complexity increases as the pattern introduce multiple classes to build the object.
Builder Pattern C# Implementation
To implement the builder pattern we are going to use a book publisher example. Here the Book class is the product and the BookCreator is the Director class that creates the book. The set of steps required to build the Book is defined by the IBookBuilder interface, which is implemented by two concrete classes, the PrintedBook and the ElectronicBook.
public class Book { public string Name { get; set; } public string Author { get; set; } public string Content { get; set; } public string Publisher { get; set; } public string Distributor { get; set; } public override string ToString() { return $" Name: {Name} \n Author: {Author} \n Content: {Content} \n Publisher: {Publisher} \n Distributor: {Distributor}\n"; } }
IBookBuilder: This is the interface that defines steps from setting the name of the book to updating the name of the distributor. Please note the interface also expose GetBook() that returns the instance of Book.
public interface IBookBuilder { void SetName(); void SetAuthor(); void SetContent(); void SetPublisher(); void SetDistributor(); Book GetBook(); }
PrintedBook: This is the first concrete class that implements the IBookBuilder interface and mock the printed book object.
public class PrintedBook : IBookBuilder { Book book = new Book(); public void SetName() { book.Name = "The greatest book"; } public void SetAuthor() { book.Author = "John Doe"; } public void SetContent() { book.Content = "The fool did not know it was impossible, so he did it"; } public void SetDistributor() { book.Distributor = "National Distributor"; } public void SetPublisher() { book.Publisher = "Pengiun"; } public Book GetBook() { return book; } }
ElectronicBook: This is the second concrete class that implements the IBookBuilder interface and mock an electronic book object.
public class ElectronicBook : IBookBuilder { Book book = new Book(); public void SetName() { book.Name = "The best book ever"; } public void SetAuthor() { book.Author = "Cristy Mall"; } public void SetContent() { book.Content = "Ignorance is a bliss"; } public void SetDistributor() { book.Distributor = "Amazon Ecart"; } public void SetPublisher() { book.Publisher = "Amazon Kindle"; } public Book GetBook() { return book; } }
BookCreator: This class acts as the Director that builds the book object representation.
public class BookCreator { private readonly IBookBuilder bookBuilder; public BookCreator(IBookBuilder builder) { bookBuilder = builder; } public void CreateBook() { bookBuilder.SetName(); bookBuilder.SetAuthor(); bookBuilder.SetContent(); bookBuilder.SetPublisher(); bookBuilder.SetDistributor(); } public Book GetBook() { return bookBuilder.GetBook(); } }
Client: This the client class that uses the Director to get the Book instance.
public class Client { static void Main(string[] args) { BookCreator creator = new BookCreator(new PrintedBook()); creator.CreateBook(); var printedBook = creator.GetBook(); Console.WriteLine(printedBook); Console.WriteLine("--------------------------------\n"); creator = new BookCreator(new ElectronicBook()); creator.CreateBook(); var electronicBook = creator.GetBook(); Console.WriteLine(electronicBook); } }
Output:
Name: The greatest book Author: John Doe Content: The fool did not know it was impossible, so he did it Publisher: Pengiun Distributor: National Distributor -------------------------------- Name: The best book ever Author: Cristy Mall Content: Ignorance is a bliss Publisher: Amazon Kindle Distributor: Amazon Ecart
This concludes the post about the Builder Design Pattern and I hope you found this post helpful. Thanks for visiting, Cheers!!!
[Further Readings: Prototype Design Pattern in C# | Top 5 Blazor Component Libraries | Abstract Factory Design Pattern in C# | Factory Method Pattern in C# | Singleton Design Pattern in C# | Introduction to Design Patterns | Microsoft C# Version History | Microsoft .NET Core Versions History | Microsoft .NET Framework Version History | Introduction to WPF in .NET Core | Useful Visual Studio 2019 extensions for database projects | Machine Learning Model Generation | Important Global Visual Studio 2019 Shortcuts | Datasets for Machine Learning | Top 7 Must-Have Visual Studio 2019 Extensions ]