建造者与装饰者模式

发布于 2024-10-13 05:43:21 字数 1431 浏览 3 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦晓ヶ微光ヅ倾城 2024-10-20 05:43:21

来自维基百科的装饰器模式文章:

在面向对象编程中,
装饰者模式是一种设计模式
允许新的/额外的行为
添加到现有对象
动态地。

披萨完全制作完成后,无需添加配料。你不会吃掉半个披萨,然后再添加另一种配料。

换句话说,构建器模式可以轻松地构造一个在构造时可以在独立方向上扩展的对象,而装饰器模式可以让您在构造之后向对象添加功能扩展。 em> 施工时间。使用装饰器模式构造对象是不好的,因为它会使对象处于不一致(或至少不正确)的状态,直到所有必需的装饰器就位为止 - 类似于使用 setter 指定可选构造函数参数的 JavaBean 问题。

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.

冬天旳寂寞 2024-10-20 05:43:21

您混淆了两种截然不同的事物。 GoF 将 Builder 归类为创建型模式,而 Decorator 则归类为结构型模式。它们的描述如下(Gamma 等人,第 1 页):

Builder (97) 将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。

装饰器 (175) 动态地将附加职责附加到对象。 装饰器为扩展功能提供了一种灵活的子类替代方案。

请注意装饰器的重点。它是子类化的灵活替代方案。子类化用于建模is-a关系。奶酪不是披萨。披萨由多种成分组成,通常使用组合来建模。

构建器模式在这里是相关的,因为成分数量如此之多,以至于需要以标准化的方式构建它们。

举一个装饰器的真实示例,我最近想记录在我的 java 应用程序中使用 jdbc 执行的查询。我通过实现一个名为 LoggingConnection 的类来实现这一点,该类扩展了 Connection 接口。

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
    ...
}

这允许我传递连接的具体实现,并在运行时扩展其功能。在这种情况下子类化会出现问题,因为您不一定知道实际返回的连接对象是什么。这是因为它是使用 DriverManager 工厂为您构建的:

Connection conn = DriverManger.getConnection(dsn);

在本例中,conn 对象是驱动程序中包含的实现,我通常不知道其名称。装饰器方法的优点在于我不必知道,并且它不依赖于特定的实现。

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.

离去的眼神 2024-10-20 05:43:21

让我们看一下BuilderDecorator 的主要特征。

Builder:(一种创建模式)

  1. 传递的参数太多到 Factory 类的客户端程序可能容易出错。
  2. 一些参数可能是可选的,与 Factory 不同,Factory 强制发送所有参数。
  3. 对象很重,并且其创建很复杂。例如构建各种类型的披萨

Decorator:(结构模式)

  1. 在运行时向对象添加行为。继承是实现该功能的关键,这既是该模式的优点也是缺点。
  2. 它增强了界面的行为。
  3. 装饰器可以被视为一种只有一个组件的退化复合体。然而,装饰器增加了额外的职责 - 它不适用于对象聚合。
  4. Decorator 支持递归组合
  5. Decorator 旨在让您无需子类化即可向对象添加职责

何时使用 Decorator

  1. 对象职责和行为应该是动态添加/删除
  2. 具体实现应该与职责和行为解耦。
  3. 当子类化成本太高而无法动态添加/删除职责时,

回到您的查询:

Builder 是 Pizza 的正确创建模式。披萨最初是用强制性成分(面包等)制作的。奶酪、意大利辣香肠、培根是可选成分,但它们仍然可以在制作过程中成为披萨的一部分。

装饰器对于在运行时为已创建的对象添加动态职责非常有用。

例如:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));

有关更多详细信息,请参阅以下帖子:

将构建器分开class(流畅的接口)

何时使用装饰器模式?

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?

动次打次papapa 2024-10-20 05:43:21

构建器模式专门用于构建和装饰器以在构建后添加特殊功能。
例如,在上面的披萨示例中,我们可以根据问题域决定使用两种模式之一。

如果辣椒片对于披萨是必不可少的,并且类似地,我们有很多成分可以添加到披萨中,其中很少有是使披萨可食用(有意义的状态)的基本成分,那么我们可以更喜欢使用 Builder。
一旦披萨制作完成,我们就可以用番茄酱、橄榄等不同的配料来装饰它……

而且,上面正确地指出它们可以一起使用,但这会增加复杂性。因此,我们应该仅在问题域需要时才明智地使用模式,否则简单的构造就足够了。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文