I'm confused about using PHP Builder pattern in practise. In many documentation they propose using the Builder like this.
require 'Pizza.php';
require 'PizzaBuiler.php';
$piza_builder=(new PizzaBuilder('medium'))
->cheeze(true)
->bacon(true)
->build();
$pizza=new Pizza($piza_builder);
Pizza class use PizzaBuilder as constructor parameter and init class properties from it.
Why not instantiate object directly from Builder ??? is this bad (Anti-Pattern).
require 'Pizza.php';
require 'PizzaBuiler.php';
$piza= Pizza::getBuilder("medium")
->cheeze(true)
->bacon(true)
->build();
The only difference between two implemnettations is to modify build() function in Builder class to return new Pizza Object instead of of returning Builder instance.
can you advice me what clean builder to use ???
I think there are some variants for the builder pattern since it is a design pattern not a specification.
Builder pattern aims to solve the problem of complex object construction. As long as it does what it intends to do, it is ok.
For sure. Consider
Pizzais a conceptual representation of an Italian dish.PizzaBuilderis a utility helps to buildPizza. APizzais good enough to exist on its own without aPizzaBuilder. I think it is not a must to accept a Builder in Product constructor.Moreover, I prefer not to include a static
PizzaBuilderinPizzabecause of the Single-responsibility principle. As stated above, a pizza is good enough to exist on its own.Pizzahas nothing to do with aPizzaBuilder. It isPizzaBuilderrequires the knowledge ofPizzato buildPizza. I will leave any logic ofPizzaconstruction stay in thePizzaBuilderand decouple it fromPizza.I would structure the code this way.
Update on 21-Apr-2022 to address comments
I think constructor is not a tool for advertising utilities built around that class. It is depends on how developer/user are knowledgeable about the framework, and base on that they program their application to achieve their purpose.
If
PizzaBuilderis standalone:If
PizzaBuilderis a static member ofPizza:We have to think about what do
PizzaBuilderandgetBuilder()mean toPizza. Are they helpingPizzato achieve something? IfPizzais a conceptual representation of an Italian dish (of course this is only my interpretation. You may have your own since you know your application best), isgetBuilder()coherent to the rest ofPizzaconstruct?In the future, if
Pizzaneed a change, what would be the possible reason? Maybe it has more ingredients to add. Maybe thePizzaBuilderdoes not fit the business needs anymore. One day, if we need a new algorithm to precisely control the water and flour ratio. We develop a newPrecisePizzaBuilderwith a complex algorithm. Then we replacePrecisePizzaBuilderwithPizzaBuilder. There would be two reasons to changePizza. It might be a hint that we couple two different things.After all, I think there is no straight right or wrong. My answer, to some extent, involve my own comprehension to your application. I may provide bias opinion because I hate pizza (not really, I love it). I may understand your application wrong. Nevertheless, most important thing is that you give each module a purpose and preserve it throughout the entire application lifespan. Foresee which part will be changed in the future and what you can do today to make your future life easier. Then you will know what decision you need to make. This is OOP, SOLID principle, and design pattern all about. To make code flexible and maintainable.