Builder设计模式和Factory设计模式之间的区别是什么?
哪一种更有利?为什么?
如果我想测试和比较/对比这些模式,我如何将我的发现表示为图表?
Builder设计模式和Factory设计模式之间的区别是什么?
哪一种更有利?为什么?
如果我想测试和比较/对比这些模式,我如何将我的发现表示为图表?
当前回答
工厂模式在运行时创建一个类的具体实现,即它的主要目的是使用多态性来允许子类决定实例化哪个类。这意味着在编译时我们不知道将要创建的确切类,而Builder模式主要涉及解决伸缩构造函数反模式的问题,这是由于类的大量可选字段而产生的。在构建器模式中,没有多态性的概念,因为我们知道在编译时要构造什么对象。
这两种模式的唯一共同主题是在工厂方法和构建方法后面隐藏构造函数和对象创建,以改进对象构造。
其他回答
两者非常相似,但如果您有大量用于对象创建的参数,其中一些参数是可选的,并且具有一些默认值,请选择生成器模式。
工厂只是一个围绕构造函数(可能是不同类中的一个)的包装函数。关键区别在于,工厂方法模式要求在单个方法调用中构建整个对象,所有参数都在一行中传递。将返回最终对象。
另一方面,构建器模式本质上是一个包装器对象,它围绕着您可能希望传递到构造函数调用中的所有可能参数。这允许您使用setter方法来缓慢地建立参数列表。生成器类上的另一个方法是build()方法,它简单地将生成器对象传递到所需的构造函数中,并返回结果。
在像Java这样的静态语言中,当您有多个(可能是可选的)参数时,这就变得更加重要,因为它避免了对所有可能的参数组合使用伸缩构造函数的要求。此外,生成器允许您使用setter方法来定义在调用构造函数后不能直接修改的只读或私有字段。
基本工厂示例
// Factory
static class FruitFactory {
static Fruit create(name, color, firmness) {
// Additional logic
return new Fruit(name, color, firmness);
}
}
// Usage
Fruit fruit = FruitFactory.create("apple", "red", "crunchy");
基本生成器示例
// Builder
class FruitBuilder {
String name, color, firmness;
FruitBuilder setName(name) { this.name = name; return this; }
FruitBuilder setColor(color) { this.color = color; return this; }
FruitBuilder setFirmness(firmness) { this.firmness = firmness; return this; }
Fruit build() {
return new Fruit(this); // Pass in the builder
}
}
// Usage
Fruit fruit = new FruitBuilder()
.setName("apple")
.setColor("red")
.setFirmness("crunchy")
.build();
比较这两个维基百科页面的代码样本可能是值得的:
http://en.wikipedia.org/wiki/Factory_method_patternhttp://en.wikipedia.org/wiki/Builder_pattern
构建模式强调创建对象的复杂性(通过“步骤”解决)
抽象模式强调(多个但相关的)对象的“抽象”。
区别很明显在生成器模式中,生成器将为您创建特定类型的对象。你必须告诉我什么建筑商必须建造。在工厂模式中,使用抽象类可以直接构建特定对象。
在这里,生成器类充当主类和特定类型类之间的中介。更抽象。
我相信,当您处理相同的代码库和不断变化的需求时,在一定的时间段内,Factory&Builder模式的用法和它们之间的区别可以更容易理解/澄清。
根据我的经验,通常从Factory模式开始,包括两个静态创建者方法,主要隐藏相对复杂的初始化逻辑。随着对象层次结构变得越来越复杂(或添加更多类型、参数),您可能最终会使用更多参数填充方法,更不用说您必须重新编译Factory模块。所有这些都会增加创建者方法的复杂性,降低可读性,并使创建模块更加脆弱。
该点可能是过渡/延伸点。通过这样做,您可以围绕构造参数创建一个包装器模块,然后您可以通过添加更多抽象(可能)和实现来表示新的(类似的)对象,而无需接触实际的创建逻辑。所以你有了“不那么复杂”的逻辑。
坦率地说,提到某种“一步或多步创建一个对象是不同的”,因为唯一的多样性因素不足以让我区分它们,因为我可以对我目前面临的几乎所有情况都使用这两种方法,而没有任何益处。这就是我最后想到的。