xxxxxxxxxx
When to Use Builder Pattern
1. When the process involved in creating an object is extremely complex, with lots of mandatory and optional parameters
2. When an increase in the number of constructor parameters leads to a large list of constructors
3. When client expects different representations for the object that's constructed
xxxxxxxxxx
// Using the Builder pattern makes sense only when your products
// are quite complex and require extensive configuration. The
// following two products are related, although they don't have
// a common interface.
class Car is
// A car can have a GPS, trip computer and some number of
// seats. Different models of cars (sports car, SUV,
// cabriolet) might have different features installed or
// enabled.
class Manual is
// Each car should have a user manual that corresponds to
// the car's configuration and describes all its features.
// The builder interface specifies methods for creating the
// different parts of the product objects.
interface Builder is
method reset()
method setSeats( )
method setEngine( )
method setTripComputer( )
method setGPS( )
// The concrete builder classes follow the builder interface and
// provide specific implementations of the building steps. Your
// program may have several variations of builders, each
// implemented differently.
class CarBuilder implements Builder is
private field car:Car
// A fresh builder instance should contain a blank product
// object which it uses in further assembly.
constructor CarBuilder() is
this.reset()
// The reset method clears the object being built.
method reset() is
this.car = new Car()
// All production steps work with the same product instance.
method setSeats( ) is
// Set the number of seats in the car.
method setEngine( ) is
// Install a given engine.
method setTripComputer( ) is
// Install a trip computer.
method setGPS( ) is
// Install a global positioning system.
// Concrete builders are supposed to provide their own
// methods for retrieving results. That's because various
// types of builders may create entirely different products
// that don't all follow the same interface. Therefore such
// methods can't be declared in the builder interface (at
// least not in a statically-typed programming language).
//
// Usually, after returning the end result to the client, a
// builder instance is expected to be ready to start
// producing another product. That's why it's a usual
// practice to call the reset method at the end of the
// `getProduct` method body. However, this behavior isn't
// mandatory, and you can make your builder wait for an
// explicit reset call from the client code before disposing
// of the previous result.
method getProduct():Car is
product = this.car
this.reset()
return product
// Unlike other creational patterns, builder lets you construct
// products that don't follow the common interface.
class CarManualBuilder implements Builder is
private field manual:Manual
constructor CarManualBuilder() is
this.reset()
method reset() is
this.manual = new Manual()
method setSeats( ) is
// Document car seat features.
method setEngine( ) is
// Add engine instructions.
method setTripComputer( ) is
// Add trip computer instructions.
method setGPS( ) is
// Add GPS instructions.
method getProduct():Manual is
// Return the manual and reset the builder.
// The director is only responsible for executing the building
// steps in a particular sequence. It's helpful when producing
// products according to a specific order or configuration.
// Strictly speaking, the director class is optional, since the
// client can control builders directly.
class Director is
// The director works with any builder instance that the
// client code passes to it. This way, the client code may
// alter the final type of the newly assembled product.
// The director can construct several product variations
// using the same building steps.
method constructSportsCar(builder: Builder) is
builder.reset()
builder.setSeats(2)
builder.setEngine(new SportEngine())
builder.setTripComputer(true)
builder.setGPS(true)
method constructSUV(builder: Builder) is
// ...
// The client code creates a builder object, passes it to the
// director and then initiates the construction process. The end
// result is retrieved from the builder object.
class Application is
method makeCar() is
director = new Director()
CarBuilder builder = new CarBuilder()
director.constructSportsCar(builder)
Car car = builder.getProduct()
CarManualBuilder builder = new CarManualBuilder()
director.constructSportsCar(builder)
// The final product is often retrieved from a builder
// object since the director isn't aware of and not
// dependent on concrete builders and products.
Manual manual = builder.getProduct()
xxxxxxxxxx
// Product class (Car) to be constructed
public class Car
{
public string Engine { get; set; }
public string Color { get; set; }
public bool HasGPS { get; set; }
public bool HasBluetooth { get; set; }
public void DisplayInfo()
{
Console.WriteLine($"Engine: {Engine}, Color: {Color}, GPS: {HasGPS}, Bluetooth: {HasBluetooth}");
}
}
// Builder interface defining steps to build the product
public interface ICarBuilder
{
void SetEngine();
void SetColor();
void SetGPS();
void SetBluetooth();
Car GetCar();
}
// Concrete builder for a Basic Car
public class BasicCarBuilder : ICarBuilder
{
private Car car;
public BasicCarBuilder()
{
car = new Car();
}
public void SetEngine()
{
car.Engine = "Basic Engine";
}
public void SetColor()
{
car.Color = "White";
}
public void SetGPS()
{
car.HasGPS = false;
}
public void SetBluetooth()
{
car.HasBluetooth = false;
}
public Car GetCar()
{
return car;
}
}
// Concrete builder for a Luxury Car
public class LuxuryCarBuilder : ICarBuilder
{
private Car car;
public LuxuryCarBuilder()
{
car = new Car();
}
public void SetEngine()
{
car.Engine = "Powerful Engine";
}
public void SetColor()
{
car.Color = "Black";
}
public void SetGPS()
{
car.HasGPS = true;
}
public void SetBluetooth()
{
car.HasBluetooth = true;
}
public Car GetCar()
{
return car;
}
}
// Director class responsible for the construction process
public class CarDirector
{
public Car BuildCar(ICarBuilder builder)
{
builder.SetEngine();
builder.SetColor();
builder.SetGPS();