You can see this and other great articles on Design Patterns here.

The Builder Design Pattern allows you to create a general guideline on how to create an object, then have different implementations on how to build parts of the object.

There are two principles in the Builder pattern; let's use an example of building an airplane to demonstrate the features:

  • The first principle is the general guideline that must be followed when building an object. For example, in building an airplane, the body must be constructed before the wings. This general guideline must be followed regardless of what type of airplane you are building.
  • The second principle are the different specifications on building the parts of the airplane. When building a jet airplane, the body must be built differently than a propeller airplane. These specifications are included in the pattern. 

With these two principles in place, let's look at the UML of the Builder pattern using the example of building an airplane:

  • The Director class contains the logic of the general guideline. In this case, its BuildAirplane method would specify that an airplane body must be built before the wing. Therefore the code for the BuildAirplane method would be:
    public Airplane BuildAirplane(IManufacturer m)      
    {         
        m.BuildBody();  //we build the body first
        m.BuildWing();  //then we build the wing
        return m.GetProduct();
    }
  • The IManufacture interface specifies the methods that all airplane manufactures must support. We see that it must be able to build the airplane body with the BuildBody method and build the wing with the BuildWing method. The GetProduct method just returns the product that is being built, which is the airplane.
  • The Manufacture class is the concrete manufacture class that has the implementation on building the parts of an airplane, hence it implements the IManufacture interface and holds a reference to the product variable, which is the airplane that is being built.
  • The Airplane class is just the final product being built.

With the Builder Design Pattern in place, the client code (calling code) to build an airplane will just be:

Airplane a = director.BuildAirplane(new Manufacture());

The Builder pattern allows you to create different concrete airplane manufactures that specify how the parts of the airplane are constructed. You can then pass in any manufacture to the director and it will build the airplane according to the specifications without having to change the client code.

The key to the Builder pattern is that:

  • You only need to determine the sequence in which the product (the airplane) is constructed in the Director.
  • You can have different implementation of the manufacturers on how the parts of an object (the body and the wings) are constructed.

The benefit of the Builder pattern is that you can swap out any implementation on how the parts are built by changing the manufactures, and the rest of the client code will not need to be changed.

In application frameworks today, we often see the Builder pattern being utilized. For example, you may have multiple configuration files that have information on database services, file location services, and notification services. These configuration files would be your manufactures, where each have their own specifications on how each part of the configuration object should be built. The director would specify the way to read the configuration file, for example, you may need to read the database services first before you read the notification services.

Below is the UML of the Builder Design Pattern, which is what we have in our example:

Below are the implementation code and the output from our example. Notice that we can pass in different airplane manufactures to the director and the airplane will be built according to the specifications:

class Program
{
    static void Main(string[] args)
    {
        Director d = new Director();

        Console.WriteLine("Build a jet airplane");
        Airplane a = d.BuildAirplane(new JetManufacturer());
        a.Show();

        Console.WriteLine("Build a propeller airplane");
        Airplane b = d.BuildAirplane(new PropellerManufacturer());
        b.Show();
    }
}    

public class Director
{
    public Airplane BuildAirplane(IManufacturer m)
    {
        m.BuildBody();
        m.BuildWing();
        return m.GetProduct();
    }
}

public interface IManufacturer
{
    void BuildBody();
    void BuildWing();
    Airplane GetProduct();
}

public class JetManufacturer : IManufacturer
{
    private Airplane product = new Airplane();

    public void BuildBody()
    {
        product.Body = "Metal Body for Jet airplane";
    }

    public void BuildWing()
    {
        product.Wing = "Metal Wing for Jet airplane";
    }

    public Airplane GetProduct()
    {
        return product;
    }
}

public class PropellerManufacturer : IManufacturer
{
    private Airplane product = new Airplane();

    public void BuildBody()
    {
        product.Body = "Wood Body for Propeller airplane";
    }

    public void BuildWing()
    {
        product.Wing = "Wood Wing for Propeller airplane";
    }

    public Airplane GetProduct()
    {
        return product;
    }
}

public class Airplane
{
    private string BodySpecification;
    private string WingSpecification;

    public string Body
    {
        get { return BodySpecification; }
        set { BodySpecification = value; }
    }

    public string Wing
    {
        get { return WingSpecification; }
        set { WingSpecification = value; }
    }

    //show the airplane
    public void Show()
    {
        Console.WriteLine(Body);
        Console.WriteLine(Wing);
    }
}

Liked this article? You can see this and other great articles on Design Patterns here.

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"