来自When would you use the Builder Pattern?,
据说构建器模式适用于Pizza示例。
为什么不装饰师? 将奶酪,意大利辣香肠,培根作为基础披萨上的附加装饰品。
是否因为奶酪/意大利辣香肠必须单独建造。我不认为,它们需要单独构建,因为它们可以随时可用。
请澄清一下。 我也在寻找装饰模式的一个很好的现实世界的例子,以及为什么它适合那个特定的例子。谢谢。
答案 0 :(得分:43)
来自维基百科的装饰模式文章:
在面向对象的编程中, 装饰图案是一种设计模式 允许新的/额外的行为 要添加到现有对象 动态。
在完全构建后,没有必要向披萨添加配料。你不要吃半个披萨,然后加一个披萨。
换句话说,Builder Pattern可以很容易地构建一个在构造时 的独立方向上可扩展的对象,而Decorator Pattern允许您向对象添加功能扩展。在施工时间之后。使用装饰器模式构造对象是不好的,因为它使对象处于不一致(或至少是不正确的)状态,直到所有必需的装饰器都到位 - 类似于使用setter指定可选构造函数参数的JavaBean问题。
答案 1 :(得分:21)
你混淆了两件截然不同的事情。 GoF将Builder分类为创建模式,而Decorator是结构模式。它们描述如下(Gamma等,第1页):
构建器(97)将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的表示。
装饰器(175)动态地将附加职责附加到对象。 装饰器为子类化提供了一种灵活的替代方法,可用于扩展功能。
注意强调装饰器。它是子类化的灵活替代方案。子类化用于建模是-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对象是驱动程序中包含的实现,我根本不知道它的名称。装饰器方法的责任在于我不必知道,并且它与特定实现无关。
答案 2 :(得分:7)
让我们了解 Builder 和 Decorator 的主要特征。
Builder :(创作模式)
Decorator :(结构模式)
何时使用装饰器:
回到您的查询:
Builder 是Pizza的正确创作模式。披萨最初是用强制性成分制作的(面包等)。奶酪,意大利辣香肠,培根是可选配料,但在制作过程中它们仍然可以成为比萨饼的一部分。
Decorator 对于在已创建的对象的运行时添加动态职责非常有用。
e.g。 :
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
有关详细信息,请参阅以下帖子:
答案 3 :(得分:2)
构建器模式专门用于构建和装饰器以在构建后添加特殊功能。 例如,在上面的Pizza示例中,我们可以决定使用基于问题域的两种模式之一。
如果Chilli Flakes对于比萨饼来说是必不可少的,同样我们有很多成分可以添加到比萨饼中,其中很少有基本的比萨饼可以食用(有意义的状态),我们可以更喜欢使用Builder。 比萨饼一旦建成,我们可以用番茄酱,橄榄等不同的配料去装饰它......
此外,正确地说,它们可以一起使用,但这会增加复杂性。因此,只有在问题域中需要时才能明智地使用模式,否则简单的构造就足够了。