Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Builder Pattern in C#

Definition of Builder Pattern: The Builder pattern separates the specification of a complex object from its actual construction. The same construction process can create different representations.

well i have a code sample of Builder Pattern like this

class Director
    {
        // Build a Product from several parts
        public void Construct(IBuilder builder)
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.BuildPartB();
        }
    }

    interface IBuilder
    {
        void BuildPartA();
        void BuildPartB();
        Product GetResult();
    }

    class Builder1 : IBuilder
    {
        private Product product = new Product();
        public void BuildPartA()
        {
            product.Add("PartA ");
        }

        public void BuildPartB()
        {
            product.Add("PartB ");
        }

        public Product GetResult()
        {
            return product;
        }
    }

    class Builder2 : IBuilder
    {
        private Product product = new Product();
        public void BuildPartA()
        {
            product.Add("PartX ");
        }

        public void BuildPartB()
        {
            product.Add("PartY ");
        }

        public Product GetResult()
        {
            return product;
        }
    }

    class Product
    {
        List<string> parts = new List<string>();
        public void Add(string part)
        {
            parts.Add(part);
        }

        public void Display()
        {
            Console.WriteLine("\nProduct Parts -------");
            foreach (string part in parts)
                Console.Write(part);
            Console.WriteLine();
        }
    }

    public class Client
    {

        public static void Main()
        {
            // Create one director and two builders
            Director director = new Director();

            IBuilder b1 = new Builder1();
            IBuilder b2 = new Builder2();

            // Construct two products
            director.Construct(b1);
            Product p1 = b1.GetResult();
            p1.Display();

            director.Construct(b2);
            Product p2 = b2.GetResult();
            p2.Display();

            Console.Read();
        }
    }

Now, i have made some changes in the above code. Is the below code still represent a Builder Pattern?

class Director
    {
        public void Construct(IBuilder builder)
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.GetResult();
        }
    }

    interface IBuilder
    {
        void BuildPartA();
        void BuildPartB();
        void GetResult();
    }

    class Builder1 : IBuilder
    {
        List<string> product = new List<string>();
        public void BuildPartA()
        {
            product.Add("PartA ");
        }

        public void BuildPartB()
        {
            product.Add("PartB ");
        }

        public void GetResult()
        {
            foreach (var p in product)
            {
                Console.WriteLine("the product created is :" + p);
            }
        }
    }

    class Builder2 : IBuilder
    {
        List<string> product = new List<string>();
        public void BuildPartA()
        {
            product.Add("PartX ");
        }

        public void BuildPartB()
        {
            product.Add("PartY ");
        }

        public void GetResult()
        {
            foreach (var p in product)
            {
                Console.WriteLine("the product created is :" + p);
            }
        }
    }
    public class Client
    {

        public static void Main()
        {

            Director director = new Director();
            IBuilder b1 = new Builder1();
            IBuilder b2 = new Builder2();
            director.Construct(b1);
            director.Construct(b2);

            Console.Read();
        }
    }

note:

I have removed the product class from the second sample code.

My question is, creating a class which handles all the object and call the method in a orderly fashion makes it a Builder Pattern? Just wanted to make sure that I understood the concept of Builder Pattern. Thanks in advance

UPDATE 1

i really couldn't understand why the second sample is not a Builder Pattern. Let me create a second example which would be simple for me to understand and would be simple for others to help me understand. The below is the code.

 interface IRoutine {
        void WakeUp();
        void GoToSchool();
        void ListenToMusic();
        void Sleep();
    }
    class person1 : IRoutine
    {
        public void GoToSchool()
        {
            Console.WriteLine("going to school");
        }

        public void ListenToMusic()
        {
            Console.WriteLine("litening to music");
        }

        public void Sleep()
        {
            Console.WriteLine("tring to sleep");
        }

        public void WakeUp()
        {
            Console.WriteLine("good morning !!!");
        }
    }
    class person2 : IRoutine
    {
        public void GoToSchool()
        {
            Console.WriteLine("going to school");
        }

        public void ListenToMusic()
        {
            Console.WriteLine("litening to music");
        }

        public void Sleep()
        {
            Console.WriteLine("tring to sleep");
        }

        public void WakeUp()
        {
            Console.WriteLine("good morning !!!");
        }
    }
    class Builder {
        public void Construct(IRoutine routine) {
            routine.WakeUp();
            routine.GoToSchool();
            routine.ListenToMusic();
            routine.Sleep();
        }
    }
    class Client {
        static void Main() {
            Builder builder = new Builder();
            IRoutine r1 = new person1();
            IRoutine r2 = new person2();

            builder.Construct(r1);
            builder.Construct(r2);

            Console.Read();
        }
    }

Is the recent example which i have provided a Builder Pattern? If not then why it is not a Builder Pattern, please help me understand.

like image 333
Lijin Durairaj Avatar asked Oct 29 '16 11:10

Lijin Durairaj


3 Answers

Your latter snippet is not an example of the builder pattern. The step where you create the final object is the crucial part of the pattern, and by removing that step your builder class effectively becomes the actual, constructed (mutable) object. In other words, if string was mutable, there wouldn't exist a StringBuilder, you would just use a hypothetical string.Append method to mutate the end object. Or, if StringBuilder returned anything other than a constructed string, it wouldn't be called a StringBuilder.

To justify the existence of a builder in practice, I would expect it either to:

  1. Provide a interface for building an immutable object, and then "freeze" it, i.e. return an immutable built instance (StringBuilder is a good example).

  2. Provide a slightly cleaner (e.g. fluent) interface for instantiating an object, compared so, say, having a huge number of constructor parameters. If the end object is mutable, however, it makes it harder to justify this, since you can set individual properties anyway.

Some examples use the builder to provide an additional layer of abstraction for building an object (i.e. allow different concrete types to be built in the same way), and then pass the abstract builder to a "director" which uses it to build the object, but I find this step irrelevant to the pattern. I would even go a step further and say that abstract builders with several methods feel like an antipattern, because they tie the construction of each concrete object to the same building process. To understand my point better, think how you would implement BoatBuilder in the example given here.

like image 181
Groo Avatar answered Sep 23 '22 00:09

Groo


IMHO this is an implementation of the builder pattern. The only fundamental difference between your implementation and the example you provided is the type of the "product". In your implementation you are making a concatenated string (I'm sure you know there are simpler ways to do this!) but the sample builds an object of type "Product".

What you use the builder pattern to construct is not really a relevant factor when determining whether you are using the builder pattern or not.

The builder pattern can be used to separate the construction of a complex object from its representation. I wouldn't class a string as a complex object that deserves implementing such complex code but you are still using a builder.

I agree with the comment left by Filip Cordas, if you know how to build your sample code you then have the power to adapt it to fit your needs. This is the power of knowing design patterns. Whether another developer agrees that your adaptation is or is not a "pure" implementation of the builder pattern is irrelevant; you've hopefully got some well designed code that meets your needs.

like image 30
mark_h Avatar answered Sep 26 '22 00:09

mark_h


In my opinion this is not a builder pattern but can be changed simply to be. Right now the only thing you are building is the builder it self. What I think would make it a "proper" builder pattern is changing your GetResult method to:

public List<string> GetResult()
        {
           return product;
        }

This way you are building a list of strings inside of your IBuilder(This is a general rule usually when you do a copy paste means you might want to rethink you implementation). The names can give you a clue your get method is not getting anything but in fact printing. But to me you implementation dose something much worse it violates the Single responsibility principle. Right now you class can change if you want to change your build process or want a new way of displaying it where as the first implementation has only one.

like image 37
Filip Cordas Avatar answered Sep 22 '22 00:09

Filip Cordas