.NET Design Patterns (The Builder Pattern)

Pattern Type: Creational

Intent: To separate the creation of complex concrete instance of a given object from its creator allowing the same creation process to create other objects of differing types while maintaining the same creation mechanism.

Description

The builder pattern provides a (usually static) instance of a class that constantly creates objects of a given type, usually by calling a complex sequence of steps within its body. This sequence of steps may (and often is) a large number of different processes or other classes that form to make a singular target object.

The builder pattern generally takes, as a parameter to its constructor, an instance of the actual builder class it needs to use to create the final object.

General uses of this pattern usually revolve around representations of the same kind of object but with each having different functionality. For example, the builder pattern often may be deployed to create a logging service, where different versions of the service may log data to different output layers, while maintaining a consistent API and/or data model for the service.

The builder pattern differs from many patterns that create a consistent object model in this fashion in that it typically creates target objects through the use of abstractions in the concrete builder implementation.

Diagram

Builder
Figure 1: The builder pattern

The following items are elements of the builder pattern:

  • Builder: The abstract interface that allows the building of target objects, given concrete builder instances to build them.
  • ConcreteBuilder: This is an actual builder instance taken in as a constructor parameter to the builder itself, which ultimately creates the target objects produced by the builder.
  • Director: The director acts as an overall master object that oversees the builder creation and setup, and makes sure it has the 'ConcreteBuilders' it requires.
  • Product: The target object produced by the builder.

Implementation in C#

The first thing to implement is usually your target object, "The Product." This is just a standard POCO object.

public class Product
{
   public Product()
   {
   }

   public string ProductPropertyOne { get; set; }

   public int ProductPropertyTwo { get; set; }

   public override string ToString()
   {
      return string.Format("Property One: {0}, Property Two: {1}",
         ProductPropertyOne, ProductPropertyTwo);
    }

}

You then need the abstract builder class. Here, I've chosen to implement this as an Interface, but you could just as easily implement this as an abstract class. Both approaches work well.

public interface IProductBuilder
{
   void SetPropertyOne(string value);
   void SetPropertyTwo(int value);
   Product GetResult();
}

Once you have an interface (or abstract), you then use that to create concrete implementations. An implementation to create "Product Type One" might look like the following:

public class ProductOneBuilder : IProductBuilder
{
   private Product _product;

   public ProductOneBuilder()
   {
      _product = new Product();
   }

   public void SetPropertyOne(string value)
   {
      _product.ProductPropertyOne = value;
   }

   public void SetPropertyTwo(int value)
   {
      _product.ProductPropertyTwo = value;
   }

   public Product GetResult()
   {
      return _product;
   }
}

As long as it implements the interface defined in the builder, everything should work okay.

Just to demonstrate the process, let's suppose you now wanted to create a "Product Two." You could add the following:

public class ProductTwoBuilder : IProductBuilder
{
   private Product _product;

   public ProductTwoBuilder()
   {
      _product = new Product();
   }

   public void SetPropertyOne(string value)
   {
      _product.ProductPropertyOne = "[" + value + "]";
   }

   public void SetPropertyTwo(int value)
   {
      _product.ProductPropertyTwo = value * 2;
   }

   public Product GetResult()
   {
      return _product;
   }
}

As you can see again, it follows the interface but implements slightly different methodology.

The final part of the puzzle is the director class. This class calls the required pieces to produce the final result.

public class Director
{
   public Product Construct()
   {
      ProductOneBuilder builder = new ProductOneBuilder();

      builder.SetPropertyOne("Red");
      builder.SetPropertyTwo(4);

      return builder.GetResult();
   }
}

If you have a Design Pattern you'd like to see implemented in C#, drop me a comment below. Until next month, practice makes perfect.

Shawty



About the Author

Peter Shaw

As an early adopter of IT back in the late 1970s to early 1980s, I started out with a humble little 1KB Sinclair ZX81 home computer. Within a very short space of time, this small 1KB machine became a 16KB Tandy TRS-80, followed by an Acorn Electron and, eventually, after going through many other different machines, a 4MB, ARM-powered Acorn A5000. After leaving school and getting involved with DOS-based PCs, I went on to train in many different disciplines in the computer networking and communications industries. After returning to university in the mid-1990s and gaining a Bachelor of Science in Computing for Industry, I now run my own consulting business in the northeast of England called Digital Solutions Computer Software, Ltd. I advise clients at both a hardware and software level in many different IT disciplines, covering a wide range of domain-specific knowledge—from mobile communications and networks right through to geographic information systems and banking and finance.

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date