开发者

Builder Vs Decorator pattern [closed]

Closed. This question is opinion-based. It is not currently accepting answers.

W开发者_开发问答ant to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 4 years ago.

Improve this question

From When would you use the Builder Pattern?,

It is said that builder pattern is appropriate for Pizza example.

Why not Decorator ? by treating Cheese, Pepperoni, Bacon as additional decorations on a base pizza.

Is it for the reason that Cheese/Pepperoni have to be built seperately. I don't think, they need to be built seperately as they can be available readymade.

Pls clarify. Am also looking for a good real-world example of decorator pattern and reason why it is the apt for that particular example. Thank you.


From wikipedia's decorator pattern article:

In object-oriented programming, the decorator pattern is a design pattern that allows new/additional behaviour to be added to an existing object dynamically.

There's no need to add toppings to a Pizza after it has been fully constructed. You don't eat half a pizza and then add another topping to it.

In other words, the Builder Pattern makes it easy to construct an object which is extensible in independent directions at construction time, while the Decorator Pattern lets you add extensions to functionality to an object after construction time. Using the decorator pattern to construct objects is bad because it leaves the object in an inconsistent (or at least incorrect) state until all the required decorators are in place - similar to the JavaBean problem of using setters to specify optional constructor arguments.


You are confusing two very different things. GoF classifies Builder as a creational pattern, while Decorator is a structural pattern. They are described as follows (Gamma et al, page 1):

Builder (97) Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Decorator (175) Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Note the emphasis on the decorator. It's a flexible alternative to subclassing. Subclassing is used to model an is-a relationship. Cheese is not a pizza. The pizza is composed of a number of ingredients, and that is usually modeled using composition.

The builder pattern is relevant here because there are such a vast number of ingredients that the need arises to construct them in a standardized way.

To take a real world example of a decorator, I recently wanted to log the queries executed using jdbc in my java application. I accomplished this by implementing a class called LoggingConnection which extended the Connection interface.

public class LoggingConnection implements Connection
{
    public static class LogEntry
    {
        public String sql;
        public int invocationCount;
        public double avgTime;
        public double maxTime;
    }

    private Connection delegate;

    private Map<String, LogEntry> log;

    public LoggingConnection(Connection delegate)
    {
        this.delegate = delegate;
        this.log = new HashMap<String, LogEntry>();
    }

    public Map<String, LogEntry> getLog()
    {
        return log;
    }

    @Override
    public void clearWarnings()
    throws SQLException
    {
        delegate.clearWarnings();
    }

    @Override
    public void close()
    throws SQLException
    {
        delegate.close();
    }

    // forwarding declarations to all other methods declared in the interface
    ...
}

This allows me to pass a concrete implemention of a connection, and extend its functionality at runtime. Subclassing would be problematic in this context, because you don't necessarily know what connection object is actually returned. This is because it's constructed for you using the DriverManager factory:

Connection conn = DriverManger.getConnection(dsn);

The conn object is in this case an implementation contained in the driver, which I generelly don't know the name of. The beuty of the decorator approach is that I don't have to know, and that it isn't tied to a specific implementation.


Lets go through key characteristics of Builder and Decorator.

Builder: ( A Creational pattern)

  1. Too Many arguments to pass from client program to the Factory class that can be error prone
  2. Some of the parameters might be optional unlike in Factory which forces to send all parameters
  3. Object is heavy and its creation is complex. e.g. building various types of pizzas

Decorator: ( A Structural pattern)

  1. Add behaviour to object at run time. Inheritance is the key to achieve this functionality, which is both advantage and disadvantage of this pattern.
  2. It enhances the behaviour of interface.
  3. 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.
  4. Decorator supports recursive composition
  5. Decorator is designed to let you add responsibilities to objects without sub-classing

When to use Decorator:

  1. Object responsibilities and behaviours should be dynamically added/removed
  2. Concrete implementations should be decoupled from responsibilities and behaviours
  3. 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?


The builder pattern is specifically used to build and Decorator to add special features post build. e.g In the Pizza example above we can decide to use one of the two pattern based on the problem domain.

If Chilli Flakes are essential for a Pizza and similarly we have a lot of ingredients to add to Pizza out of which few are elementary to make the Pizza edible(meaningful state), we can prefer to use Builder. Once the Pizza is constructed, we can later go and decorate it with different toppings like tomato sauce, olives, etc...

Also, it is stated above correctly that they can be used together but this will increase complexity. So we should use patterns wisely only when it is needed in the problem domain, else a simple construction will suffice.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜