首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Builder Vs Decorator pattern

Builder Vs Decorator pattern
EN

Stack Overflow用户
提问于 2011-01-22 22:22:50
回答 4查看 20K关注 0票数 38

来自When would you use the Builder Pattern?

据说构建器模式适用于Pizza示例。

为什么不是装饰者呢?把芝士、意大利香肠、培根当作披萨上的额外装饰品。

是不是因为芝士/胡椒香肠必须分开制作。我不认为,它们需要单独构建,因为它们可以现成。

请澄清。我也在寻找装饰器模式的一个很好的现实世界的例子,以及为什么它是那个特定例子的合适的原因。谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-01-22 22:44:19

摘自维基百科的装饰者模式文章:

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

披萨完全制作完成后,没有必要在上面添加配料。你不会吃了半个披萨,然后再加一层配料。

换句话说,Builder模式使构造在构造时在独立方向上可扩展的对象变得很容易,而Decorator模式允许您在构造时向对象添加功能扩展。使用装饰器模式来构造对象是不好的,因为在所有必需的装饰器就位之前,它会使对象处于不一致(或至少不正确)的状态-类似于使用设置器指定可选构造函数参数的JavaBean问题。

票数 50
EN

Stack Overflow用户

发布于 2011-01-22 22:41:14

你混淆了两个截然不同的东西。GoF将生成器归类为创建型模式,而装饰器则属于结构型模式。它们的描述如下(Gamma等人,第1页):

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

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

注意对装饰器的强调。它是子类化的一种灵活选择。子类化用于对 is -a关系进行建模。奶酪不是披萨。披萨是由许多成分组成的,这通常是使用组合建模的。

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

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

代码语言:javascript
复制
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
    ...
}

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

代码语言:javascript
复制
Connection conn = DriverManger.getConnection(dsn);

在这种情况下,conn对象是一个包含在驱动程序中的实现,我一般不知道它的名称。装饰器方法的美妙之处在于我不需要知道,而且它不依赖于特定的实现。

票数 21
EN

Stack Overflow用户

发布于 2016-08-14 01:29:08

让我们来看看Builder和Decorator的主要特征。

Builder:(一个创造性的模式)

  1. 从客户端程序传递到工厂类的参数太多,这很容易出错
  2. 一些参数可能是可选的,而不像工厂中强制发送所有的参数很繁重,而且它的创建也很复杂。例如,建立各种类型的披萨

Decorator:(一种结构模式)

  1. 在运行时向对象添加行为。继承是实现这一功能的关键,这也是该模式的优点和缺点。
  2. 它增强了interface.
  3. Decorator的行为,可以看作是只有一个组件的退化组合。然而,装饰器添加了额外的职责-它不是为对象而设计的aggregation.
  4. Decorator支持递归composition
  5. Decorator旨在让您在没有sub-classing

的情况下向对象添加职责

何时使用装饰器

added/removed

  • Concrete实现应该从职责中解耦,而behaviours

  • When子类化对于动态添加/删除responsibilities

来说代价太高,因此

  1. 对象的职责和行为应该是动态的

返回到您的查询:

Builder是Pizza正确的创作模式。披萨最初是用强制配料制作的(面包等)。奶酪,胡椒香肠,培根是可选的配料,但在制作过程中,它们仍然可以作为披萨的一部分。

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

例如:

代码语言:javascript
复制
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));

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

Keeping builder in separate class (fluent interface)

When to Use the Decorator Pattern?

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4768349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档