Lets go through key characteristics of Builder and Decorator.
Builder: ( A Creational pattern)
- Too Many arguments to pass from client program to the Factory class that can be error prone
- Some of the parameters might be optional unlike in Factory which forces to send all parameters
- Object is heavy and its creation is complex. e.g. building various types of pizzas
Decorator: ( A Structural pattern)
- Add behaviour to object at run time. Inheritance is the key to achieve this functionality, which is both advantage and disadvantage of this pattern.
- It enhances the behaviour of interface.
- Decorator can be viewed as a degenerate Composite with only one component. However, a Decorator adds additional responsibilities - it isn't intended for object aggregation.
- Decorator supports recursive composition
- Decorator is designed to let you add responsibilities to objects without sub-classing
When to use Decorator:
- Object responsibilities and behaviours should be dynamically added/removed
- Concrete implementations should be decoupled from responsibilities and behaviours
- When sub - classing is too costly to dynamically add/remove responsibilities
Coming back to your query:
Builder is right creational pattern for Pizza. Pizza is created with mandatory ingredients initially ( Bread etc). Cheese, Pepperoni, Bacon are optional ingredients but still they can be part of pizza during build process.
Decorator is useful for adding dynamic responsibilities at run-time for already created object.
e.g. :
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
Refer to below posts for more details:
Keeping builder in separate class (fluent interface)
When to Use the Decorator Pattern?