来自When would you use the Builder Pattern?,
据说构建器模式适用于Pizza示例。
为什么不是装饰者呢?把芝士、意大利香肠、培根当作披萨上的额外装饰品。
是不是因为芝士/胡椒香肠必须分开制作。我不认为,它们需要单独构建,因为它们可以现成。
请澄清。我也在寻找装饰器模式的一个很好的现实世界的例子,以及为什么它是那个特定例子的合适的原因。谢谢。
发布于 2011-01-22 22:44:19
摘自维基百科的装饰者模式文章:
在面向对象编程中,装饰器模式是一种设计模式,它允许将新的/附加的行为动态地添加到现有的对象中。
披萨完全制作完成后,没有必要在上面添加配料。你不会吃了半个披萨,然后再加一层配料。
换句话说,Builder模式使构造在构造时在独立方向上可扩展的对象变得很容易,而Decorator模式允许您在构造时向对象添加功能扩展。使用装饰器模式来构造对象是不好的,因为在所有必需的装饰器就位之前,它会使对象处于不一致(或至少不正确)的状态-类似于使用设置器指定可选构造函数参数的JavaBean问题。
发布于 2011-01-22 22:41:14
你混淆了两个截然不同的东西。GoF将生成器归类为创建型模式,而装饰器则属于结构型模式。它们的描述如下(Gamma等人,第1页):
生成器 (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
...
}这允许我传递连接的具体实现,并在运行时扩展其功能。在这种情况下,子类化是有问题的,因为您不一定知道实际返回的是什么connection对象。这是因为它是使用DriverManager工厂为您构建的:
Connection conn = DriverManger.getConnection(dsn);在这种情况下,conn对象是一个包含在驱动程序中的实现,我一般不知道它的名称。装饰器方法的美妙之处在于我不需要知道,而且它不依赖于特定的实现。
发布于 2016-08-14 01:29:08
让我们来看看Builder和Decorator的主要特征。
Builder:(一个创造性的模式)
Decorator:(一种结构模式)
的情况下向对象添加职责
何时使用装饰器
added/removed
来说代价太高,因此
返回到您的查询:
Builder是Pizza正确的创作模式。披萨最初是用强制配料制作的(面包等)。奶酪,胡椒香肠,培根是可选的配料,但在制作过程中,它们仍然可以作为披萨的一部分。
装饰器对于在运行时为已经创建的对象添加动态职责非常有用。
例如:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));有关更多详细信息,请参阅以下帖子:
https://stackoverflow.com/questions/4768349
复制相似问题