Geeks With Blogs
Dheeman Dutta Just Another Blog.....
Object creation as you might remember was done using the Factory Pattern (as mentioned in an blog previously “Design patterns - Part 1-Factory Pattern in .NET”. But not always creating involves a single process. Sometimes it takes more than one processes to create a full product, and then creation of these separate objects in a particular way needs the Builder pattern. But Builder pattern will not be suffice in the scenario, that I’m going to present now. A factory along with a builder will do the trick for us.
 
Let us consider , we are making a Computer.. We need a keyboard, mouse also to give the computer a full sense. So our creation process is not limited to making only the computer(read CPU ) itself, you also need to create the Mouse,Keyboard and many other accessories.
 
Lets assume we have classes for Mouse,Keyboard etc.. like as follows….
 
 
public class KeyBoard
    {
        public KeyBoard() { Console.WriteLine("This is a good Keyboard"); }
 
        public KeyBoard(bool isremote) { if (isremote) { Console.WriteLine("This is a remote Keyboard "); } else { Console.WriteLine("Good Silver Keyboard"); } }
    }
 
 
public class Mouse
    {
       public Mouse() { Console.WriteLine("This is a optical mouse"); }
    }
 
public class WebCam
    {
        public WebCam() { Console.WriteLine("This is a 2 MP Camera"); }
    }
 
 
Just like the “Factory Pattern” (ref. Design patterns - Part 1-Factory Pattern in .NET) we will still be having an abstract class (Computer class here) . The only addition is that ,because a full computer needs to have a “KeyBoard” and “Mouse” , the Computer class here has two memebers for these corresponding objects.
The code follows
 
public abstract class Computer
    {
       KeyBoard keyBoard;
       Mouse mouse;
 
      
       public KeyBoard KeyBoard
       {
           get { return keyBoard; }
           set { keyBoard = value; }
       }
 
      
       public Mouse Mouse
       {
           get { return mouse; }
           set { mouse = value; }
       }
     
     
    }
 
 
Now just as in the the “Factory Pattern” (ref. Design patterns - Part 1-Factory Pattern in .NET) we will create the individual computers. In our sample we’re creating three type sof computers..lets see
 
 
public class Brand1Computer:Computer
    {
 
    }
 
public class Brand2Computer:Computer
    {
    }
 
public class CustomAssembledComputer:Computer
    {
        private WebCam webCam;
 
        public WebCam WebCamera
        {
            get { return webCam; }
            set { webCam = value; }
        }
     
    }
 
Now take a close look in the abobe three classes . While the first two just inheris the abstract class, the last one adds another functionality to itself, i.e. the WebCamera and thus have a property for that.
 
Now we need to create the builder, in order to create the whole assembly.
 
public abstract class Builder
    {
       public abstract void CreateFullComputer(ref Computer computer);
    }
 
The Builder as you might see is an abstract class. The individual builder classes still needs to be put in place. In each of these individual classes we will create the whole assembly in the order we want.
 
 
 
 
public class Brand1ComputerBuilder : Builder
    {
       public override void CreateFullComputer(ref Computer computer)
       {
          
           Brand1Computer brand1 = (Brand1Computer)computer;
           brand1.KeyBoard = null;
           brand1.Mouse = new Mouse();
 
       }
    }
 
 
 
public class Brand2ComputerBuilder:Builder
    {
        public override void CreateFullComputer(ref Computer computer)
        {
              
            Brand2Computer brand2 = (Brand2Computer)computer;
            brand2.KeyBoard = new KeyBoard();
            brand2.Mouse = new Mouse();
 
        }
    }
 
 
public class CustomAssembledComputerBuilder:Builder
    {
       public override void CreateFullComputer(ref Computer computer)
       {
           
           CustomAssembledComputer customComp = (CustomAssembledComputer)computer;
           customComp.KeyBoard = new KeyBoard(true);
           customComp.Mouse = new Mouse();
           customComp.WebCamera = new WebCam();
       }
    }
 
 
 
So we have our individual builders. Just take a closer look first at  “Brand1ComputerBuilder” where I have opted that this assembly will not have a mouse. “Brand2ComputerBuilder” however is a more general assembly in all respects. “CustomAssembledComputerBuilder” however , adds a webcamera to its accessories list during creation. So you might see that , what I mentioned during my first few lines , that a builder is more necessary when multiple creational steps are the present.
 
We have not finished yet…. !! Where is the actual factory that creates the computer ( as in the Factory Pattern” )
 
 
 
We will create that now..
 
public enum ComputerType
    {
        BrandOne,
        BrandTwo,
        Custom
    }
 
   public class ComputerFactory
    {
        Hashtable _registered = new Hashtable();
        Hashtable _loaded = new Hashtable();
       Hashtable _builders = new Hashtable();
 
       public void Register(ComputerType computerType,Type type,Builder builder)
       {
           _registered.Add(computerType, type);
           _builders.Add(computerType, builder);
       }
 
       public Computer CreateComputer(ComputerType computerType)
       {
           if (_loaded[computerType] == null)
                  LoadComputer();
          
 
           Computer computer = (Computer)_loaded[computerType];
 
           if (_builders[computerType] != null)
           {
               Builder builder = (Builder)_builders[computerType];
               builder.CreateFullComputer(ref computer);
           }
 
           return computer;
       }
 
       private void LoadComputer()
       {
           foreach (DictionaryEntry obj in _registered)
           {
               Type type = (Type)obj.Value;
               ConstructorInfo cinfo = type.GetConstructor(new Type[] { });
               _loaded.Add(obj.Key, (Computer)cinfo.Invoke(new object[] { }));
           }
       }
 
    }
 
 
 
If you take a close look in the factory class here and the factory class in the “Factory Pattern” (ref. Design patterns - Part 1-Factory Pattern in .NET) you will find a few subtle differences. Lets analyse them a bit…
 
Now we have a new Hashtable declared
 
         
Hashtable _builders = new Hashtable();
 
The Register method now takes in a new parameter along with the old parameters.
 
public void Register(ComputerType computerType,Type type,Builder builder)
 
The builder is getting passed as a parameter now during registration. Let’s see how that helps. Within the “Register” method we have a new line
_builders.Add(computerType, builder);
 
 What this does is that, this maps the enum type with a corresponding builder object in the Hash table.
 
The “CreateComputer” method has also changed a bit. Along with the usual factory code we have the following code block added to it.
 
 
if (_builders[computerType] != null)
           {
               Builder builder = (Builder)_builders[computerType];
               builder.CreateFullComputer(ref computer);
           }
 
 
 
Therefore , unlike the Factory pattern, we now check the builders hashtable for null and actually load the corresponding builder from the _builders hashtable. And once we have this object we will call the “CreateFullComputer” method of the builder. This method takes in a computer and creates the full assembly , as mentooned in its builder and retuns the Computer object.
 
 
The “LoadComputer” method is still same as it was before.
 
Now its time to actually create these objects and see
 
static void Main(string[] args)
        {
            ComputerFactory cFactory = new ComputerFactory();
 
            cFactory.Register(ComputerType.BrandOne, typeof(Brand1Computer), new Brand1ComputerBuilder());
            cFactory.Register(ComputerType.BrandTwo, typeof(Brand2Computer), new Brand2ComputerBuilder());
            cFactory.Register(ComputerType.Custom, typeof(CustomAssembledComputer), new CustomAssembledComputerBuilder());
 
            Console.WriteLine("Brand 1 :");
            Computer computer = cFactory.CreateComputer(ComputerType.BrandOne);
            Console.WriteLine("Brand 2 :");
            computer = cFactory.CreateComputer(ComputerType.BrandTwo);
            Console.WriteLine("Custom :");
            computer = cFactory.CreateComputer(ComputerType.Custom);
 
            Console.ReadKey();
 
        }
 
 
 
 
The output is as follows
 
Brand 1 :
This is a optical mouse
Brand 2 :
This is a good Keyboard
This is a optical mouse
Custom :
This is a remote Keyboard
This is a optical mouse
This is a 2 MP Camera
 
 
 
Posted on Tuesday, January 1, 2008 9:43 PM | Back to top


Comments on this post: Design patterns - Part 4-Builder Pattern in .NET

# re: Design patterns - Part 4-Builder Pattern in .NET
Requesting Gravatar...
Difficult to understand ComputerType class. Y we need Hashtable representation?
Left by Abdul on Feb 19, 2010 9:52 AM

Your comment:
 (will show your gravatar)


Copyright © Dheeman Dutta | Powered by: GeeksWithBlogs.net