Link to home
Start Free TrialLog in
Avatar of XTO
XTO

asked on

How do I pass arguments in a Builder design pattern ?

Suppose I have user input values that I don't know ahead of time and I want to pass these values while creating the product.
Do I pass the values to the Director class or do I pass the values to the Builder class before passing the Builder object to the Director?

Possibility #1:

So, if I pass the values to the Director class, it would look like this:

             IProductBuilder myProduct = new ExpensiveProductBuilder();
            Director director = new Director();
            director.BuildProduct(myProduct, argument1, argument2);

Open in new window


Then in the Director class:

    class Director
    {
        public BuildProduct(IProductBuilder anyProduct, Base arg1, Top arg2)
        {
            anyProduct.BuildBase(arg1);
            anyProduct.BuildTop(arg2);         
        }
    }

Open in new window



Possibility #2

On the other hand, what if I pass the values to the Builder class before passing the Builder object to the Director?
So, if I pass the arguments into the Builder class it looks like this:

            IProductBuilder myProduct = new ExpensiveProductBuilder(argument1, argument2);
            Director director = new Director();
            director.BuildProduct(myProduct);

Open in new window



And then the Builder class would look like this:

    class ExpensiveProductBuilder
    {
        Product baseProduct = new Product();
        Base arg1;
        Top arg2;

        public ExpensiveProduct(Base arg1, Top arg2)
        {
            this.arg1 = arg1;
            this.arg2 = arg2;
        }

        public void BuildBase(arg1) { /* . . . */ }
        public void BuildTop(arg2) { /* . . . */ }
    }

Open in new window



Which of those two possibilities, if either, is the correct way or the usual way of passing arguments in a Builder pattern ?
If neither, then how is it done? Thanks.
Avatar of sarabande
sarabande
Flag of Luxembourg image

Generally, a 'director' should not know about details. so you should not pass arguments to the director but to the product.

Director director = new Director();

if you always use a new director for each new product, you pretty well could do without a director as well or create it as an 'assistant' within the product class. also a 'product builder' class rarely has a  useful role. why not simply 'build' the product by using a 'create' or 'build' member function? or 'build it with the constructor:

IProduct myProduct = new ExpensiveProduct(argument1, argument2);

Open in new window


you already called it 'myProduct'. so what is the benefit of an additional 'Builder'.


if you would make the 'Director' a singleton then it could have a valuable role in order to manage 'all' products. or virtually create/build different products by using factory pattern.

Sara
Avatar of XTO
XTO

ASKER

"if you always use a new director for each new product"

I agree that creating the Director as a singleton is better.
I wasn't trying to imply that I would create a new director with each type of builder.

I would be using the same Director(which is what the Builder pattern calls for) for building a variety of products..

Director director = new Director(); // I can refactor this as a Singleton later.

IProductBuilder myProduct = new ExpensiveProductBuilder();
IProductBuilder yourProduct = new QualityProductBuilder();
IProductBuilder hisProduct = new CheapProductBuilder();
IProductBuilder herProduct = new ImportedProductBuilder();

director.BuildProduct(myProduct, argument1, argument2);
director.BuildProduct(yourProduct, argument3, argument4);
director.BuildProduct(hisProduct, argument5, argument6);
director.BuildProduct(herProduct, argument7, argument8);

Open in new window


". . . so what is the benefit of an additional 'Builder'."
The benefit of additional builders is to remove the complexity of building the product out of the product, especially when there are many possible variations of each.
It can also reduce the number of parameters to a constructor, and reduce the number of constructors.

"so you should not pass arguments to the director but to the product."
Do you mean, " . . . but to the Builder ?"
to remove the complexity of building the product out of the product

actually OOD means that objects act like real objects. if for example humans would have need a builder rather than grow themselves i doubt that we would be alive now.

i know there are a lot of bad samples like a string builder to build strings but you should know that most class libraries nowadays have a better design and provide complete objects which don't need helpers and builders.

Sara
Avatar of XTO

ASKER

Although the philosophy of OOD is very interesting to me and I enjoy thinking about it, and although I find the discussion of the subject to be fascinating, I started this thread to get an answer to an exact and specific question: "how do I pass arguments in a builder pattern?"

So, in a correct implementation of the Builder pattern, arguments should be sent to the Builder object; is that right? On the other hand, another possibility is that in a correct implementation of the Builder pattern, no arguments should be sent. In other words, if arguments need to be sent, then the Builder pattern can not be used as it does not allow for that.

The points on this thread go to the academically accurate answer to that question, with perhaps references to a well accepted GOF related specs paper, or a Martin Fowler article, or some Microsoft best practice document,  or an ACM article, or some similar industry standard consortium statement. Thanks.
How do I pass arguments in a Builder design pattern ?
this was only the title of your question. in the body you described two possible concepts and asked

Which of those two possibilities, if either, is the correct way
'if either' obviously meant that that other designs were possible as well. if you changed your mind regarding this point you may consider to ask a new question where this is made clear already in the initial post.

generally, i don't think that builder and manager classes like the ones you have posted, are an appropriate design. they add complexity to the design concept which is not needed and violate OOD principles. why should you have a builder if you want to create a product? why should you use a manager to do the build if you all could do with the product class itself?

The points on this thread go to the academically accurate answer to that question
you should 'request for attention' (see button at your original question) and let the Moderators add some more topic areas and reschedule the question. currently it is only a little chance that other experts will participate and read the whole thread to end.

i don't think that there are published 'design patterns' of using product, builder, and manager classes. or if there are such articles, they probably would focus onto other points since 'design patterns' actually are more than the question which one of a bunch of related classes will get which arguments. they are concepts how a non-trivial functionality could be designed by using OOP design patterns. in almost all cases they are not specific for one programming language. for example the factory pattern describes how you virtually can create classes derived from the same baseclass. but the factory pattern will not determine whether you need an extra factory class or whether the common baseclass could handle the factory itself. of course if you ask for a c# design pattern, it is more likely that you also get a concrete sample implementation, but this not the pattern.

from an OOP Point of view, you always would try to avoid redundancy and encapsulate member data into the classes which owns them. following the last point you would have code like

IProductBuilder myProductBuilder = new ExpensiveProductBuilder();
Director director = new Director();
MyProduct myProduct = director.BuildProduct(myProductBuilder);
myProduct.SetArguments(arg1, arg2);

Open in new window



what is only slightly different to your first possibility but avoids redundancy when passing the arguments. it also shows the redundancy of the builder and the manager as long as they don't get a reasonable role in this scenario.

note, if the arguments are not properties of the product but tell the builder how to build the product, it would make much more sense to have a builder. and of course you would pass the arguments to the builder and not to the manager in this case.

Sara
Avatar of XTO

ASKER

. . .  if the arguments . . . tell the builder how to build the product, . . . you would pass the arguments to the builder . . . .

Based on that statement, then possibility #2 from the original question fits that rule:

IProductBuilder myProduct = new ExpensiveProductBuilder(argument1, argument2);

Open in new window

Please confirm if that is correct. If so, then I will award full points and close the question. Thanks.
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of XTO

ASKER

I will award full points for the information that possibility #2 is the better option. References are not necessary, but merely "preferred."
Thanks for the additional information on the factory pattern. That is also interesting to me.
Now that the original question has been answered, I can comment on some of the philosophical and open-ended statements.

actually OOD means that objects act like real objects. if for example humans would have need a builder rather than grow themselves i doubt that we would be alive now.

Expanding from the premise that software objects should emulate actual objects, most things do not build themselves. automobiles, phones, pharmaceuticals, homes, clothes, etc, are indeed assembled. Both the assembled product and the thing that assembles it are objects. In other words, the builder is also  an object in the real world.

Even for people, when they are conceptually abstracted for software, their real world context does "build" the instance of that abstraction. For example, in the real world context of a company, an employee person needs to have the company assign them a role (manager, consultant, sales), then assign them a department, a geographic region, etc, and then based on those assignments (properties), figure out and calculate other details for the employee such as calculating salary, vacation time, network security rights, building access permissions, etc.
A software that emulates and automates that would need the properties sent to the object that builds.
In such a case, it would be handy to have a "manager builder" that accepts other properties, and then both assigns those properties, and then also calculates the other variables.
People who are abstracted for software in universities, militaries, social programs, etc, can be similarly addressed (no pun intended).

Even in the case of an actual biological human where the building mechanism is internal in the real world, there is still an internally distinct set of mechanisms for processing DNA data and building the tissue and organs which follow. If we were building a human genome modeling software, for instance, the class abstraction in the virtual software realm could contain a class for receiving DNA sequence arguments, converting that to genetic information, and then building various organs or tissue: heart, liver, bone.
Avatar of XTO

ASKER

I got the answer to my question and some other helpful suggestions upon which I can follow up on later.
most things do not build themselves
probably the word 'build' is the cause for the misunderstanding of what i said. if we build a software object we normally are not describing a life-cycle or a growing process but create an already complete object. if you don't add the known properties and member data directly to the object when creating it, but use a 'builder' you always should ask why the creator (caller) needs to know of the existence of a builder at all and have to create two objects instead of one. in other words, if an object needs an assistent or builder,  this should be an internal matter of the object but nothing what the 'users' need to consider.

assume your objects are persistent and have their information stored in a database. obviously you would not create an SQL environtment handler, an SQL Database handler, an SQL statement builder, an SQL reader, an SQL translator at every place where you want to create an object that gets its data from the database. same applies if you want to store memory objects. but it is also clear that all these helpers were needed when creating objects which already were persistent.

MyPersistentProduct p = new MyPersistentProduct(productNumber);
p.LoadPersistentData();

Open in new window


a good design always will try to encapsulate the knowledge how something was implemented away from the users of the objects to the objects themselves. that way you easily could change the methods to retrieve data. in the above sample, you might want to get the product data from a Server instead from the database, what you easily can handle in the LoadPersistentData() function. note, LoadPersistentData could be a baseclass member function, or could use a builder or manager, whatever.

Sara