14
SepBuilder Design Pattern
Builder Design Pattern
Builder Design Pattern is an important design pattern in C# that allows you to develop complex objects step by step. It lets you build a complicated item by separating the creation process from the representation, allowing you to generate several representations of the same type of object. This pattern gives a straightforward way to build an object, especially when the process involves multiple steps or distinct configurations.
In this design pattern tutorial, we will look at the Builder Design Pattern, explaining what it is, when to use it, and how to implement it using examples. We will begin by studying "What is the Builder Design Pattern?"
What is a Builder Pattern?
- The Builder pattern in C# is an object-oriented design pattern used to build complex objects step by step.
- It differentiates between the construction process and the representation, allowing the same construction process to generate many representations.
- A builder class typically has methods for configuring the various components of the product and a final Build function that creates the fully built item.
When to use the builder pattern?
- Complex Object Construction: When an object requires sophisticated initialization or building that includes numerous processes or configurations.
- Multiple Representations: When a single construction process must produce multiple representations or configurations of an entity.
- Immutability: When you want to make immutable objects with different settings.
- Code Readability and Maintainability: Encapsulate the building logic and separate it from the object representation to improve code readability and maintainability.
Builder Pattern - UML Diagram & Implementation
The UML class diagram for the implementation of the builder design pattern is given below:
The classes, interfaces, and objects in the above UML class diagram are as follows:
1. Builder
- Role: Defines the abstract interface for manufacturing product pieces.
- Responsibilities: Provide methods for building each component of the product and, in most cases, a way to retrieve the finished result.
Example
public interface IHouseBuilder
{
void BuildWalls();
void BuildRoof();
void BuildDoors();
void BuildWindows();
House GetResult();
}
Explanation
The ConcreteHouseBuilder class implements the IHouseBuilder interface and creates a House object with specific properties, such as brick walls, a tile roof, wooden doors, and glass windows. It has methods for building each component of the house and a GetResult method that returns the final House object.
2. ConcreteBuilder
- Role: Implements the Builder interface for creating and assembling Product components.
- Responsibilities: Contains the precise implementation for each construction phase and the finished result.
Example
public class ConcreteHouseBuilder : IHouseBuilder
{
private House _house = new House();
public void BuildWalls() { _house.Walls = "Brick"; }
public void BuildRoof() { _house.Roof = "Tile"; }
public void BuildDoors() { _house.Doors = "Wooden"; }
public void BuildWindows() { _house.Windows = "Glass"; }
public House GetResult() { return _house; }
}
Explanation
The ConcreteHouseBuilder class, which implements the IHouseBuilder interface, creates a house object with brick walls, a tile roof, wooden doors, and glass windows. It also includes a method for returning the completed house.
3. Product
- Role: The complex thing under construction.
- Responsibilities: Represents the end product of the creation process, which is often a class with numerous attributes that may be configured using the builder.
Example
public class House
{
public string Walls { get; set; }
public string Roof { get; set; }
public string Doors { get; set; }
public string Windows { get; set; }
public override string ToString()
{
return $"House with {Walls} walls, {Roof} roof, {Doors} doors, and {Windows} windows.";
}
}
Explanation
The House class represents a house and has attributes for walls, roofs, doors, and windows that are described as strings. It overrides the ToString method and returns a descriptive string of the house's properties.
4. Director
Example
public class HouseDirector
{
private IHouseBuilder _builder;
public HouseDirector(IHouseBuilder builder)
{
_builder = builder;
}
public void ConstructHouse()
{
_builder.BuildWalls();
_builder.BuildRoof();
_builder.BuildDoors();
_builder.BuildWindows();
}
}
Explanation
The HouseDirector class manages the construction of a House by utilizing an IHouseBuilder instance. It describes the sequence of building processes in its ConstructHouse technique to ensure that the house is created in the proper order. This distinction enables different builders to be employed interchangeably, resulting in diverse styles of homes.
How Does the Builder Pattern Work?
Example
// Product
public class House
{
public string Walls { get; set; }
public string Roof { get; set; }
public string Doors { get; set; }
public string Windows { get; set; }
public override string ToString()
{
return $"House with {Walls} walls, {Roof} roof, {Doors} doors, and {Windows} windows.";
}
}
// Builder Interface
public interface IHouseBuilder
{
void BuildWalls();
void BuildRoof();
void BuildDoors();
void BuildWindows();
House GetResult();
}
// ConcreteBuilder
public class ConcreteHouseBuilder : IHouseBuilder
{
private House _house = new House();
public void BuildWalls() { _house.Walls = "Brick"; }
public void BuildRoof() { _house.Roof = "Tile"; }
public void BuildDoors() { _house.Doors = "Wooden"; }
public void BuildWindows() { _house.Windows = "Glass"; }
public House GetResult() { return _house; }
}
// Director
public class HouseDirector
{
private IHouseBuilder _builder;
public HouseDirector(IHouseBuilder builder)
{
_builder = builder;
}
public void ConstructHouse()
{
_builder.BuildWalls();
_builder.BuildRoof();
_builder.BuildDoors();
_builder.BuildWindows();
}
}
// Usage
public class Program
{
public static void Main()
{
IHouseBuilder builder = new ConcreteHouseBuilder();
HouseDirector director = new HouseDirector(builder);
director.ConstructHouse();
House house = builder.GetResult();
System.Console.WriteLine(house);
}
}
Explanation
This example uses the Builder pattern, with House as the product class, IHouseBuilder as the builder interface, ConcreteHouseBuilder as the concrete builder that implements the construction phases, and HouseDirector directing the building process. The Program class builds a house and prints its description.
Output
House with Brick walls, Tile roof, Wooden doors, and Glass windows.
Advantages of the Builder Pattern:
- Separation of Concerns: Separates the building logic of complex objects from their representation.
- Flexible construction: Allows for multiple representations of a product using the same method.
- Readability and Maintenance: Improves code readability and maintainability by encapsulating the construction process.