1) What have we at beginning ?
We have simple relation one to many. We have some abstract "Product" which can have many elements which we name "ProductElement"
* @var ProductElement
private $elements = ;
* @param ProductElement $productElement
public function addElement(ProductElement $productElement)
$this->elements = $productElement;
* @var string
* @param string $name
$this->name = $name;
2) How we create these objects ?
We have some client in which we just call constructor of product and next we add elements to it.
$product = new Product();
So the essence of issue is creating products. Let's think a little of above solution.
3) What are the disadvantages ?
First of all we create explicitly instances of product and its elements. Client must to know explicitly names of class which implements "Product" and "ProductElement"
It's not good, we don't want this, we want to encapsulate this. We wan't to loose coupling between product and client.
Note: Client shouldn't be bothered information which class actually implement "Product". He should only receive some object which meets "Product" interface, nothing more
So we need to provide solution in which we don't give information to client about objects which are concrete implementation.
It's desirable to be able create product many times in many places. In above code it's bothersome. We would like to present some nicer interface for client.
Note: We can call "addElement" one time, two times, or more: three, four, five ...
Every time we can add different elements. So actually "Product" is designed for representing compound objects even if it has one method. So "Builder" here is strongly advisable
4) How we can improve this ?
We can move creating special object named "Builder" for creating "Product" objects. Let's move to step 2.