Builder设计模式和Factory设计模式之间的区别是什么?
哪一种更有利?为什么?
如果我想测试和比较/对比这些模式,我如何将我的发现表示为图表?
Builder设计模式和Factory设计模式之间的区别是什么?
哪一种更有利?为什么?
如果我想测试和比较/对比这些模式,我如何将我的发现表示为图表?
当前回答
对于设计模式,通常没有适用于所有情况的“更有利”解决方案。这取决于您需要实施什么。
来自维基百科:
Builder专注于构建一步一步复杂的物体。摘要工厂强调产品系列对象(简单或复杂)。生成器将产品作为最终产品返回步骤,但就抽象而言工厂关心,产品得到立即返回。生成器通常构建一个复合。通常,设计开始时使用工厂方法(不那么复杂,更多可定制,子类激增)并向抽象工厂发展,原型或生成器(更灵活,更复杂)发现更灵活的地方需要。有时创造模式是互补的:构建者可以使用要实现的其他模式构建哪些组件。摘要工厂、建造商和原型可以使用Singleton实现。
工厂设计模式维基百科条目:http://en.wikipedia.org/wiki/Factory_method_pattern
构建器设计模式的维基百科条目:http://en.wikipedia.org/wiki/Builder_pattern
其他回答
生成器和抽象工厂生成器设计模式在某种程度上与抽象工厂模式非常相似。这就是为什么在使用其中一种或另一种情况时,能够区分不同的情况是很重要的。在抽象工厂的情况下,客户端使用工厂的方法来创建自己的对象。在Builder的例子中,Builder类被指示如何创建对象,然后被要求创建对象,但是类的组合方式取决于Builder类,这一细节决定了两种模式之间的区别。产品通用接口在实践中,由混凝土建设者创建的产品具有明显不同的结构,因此如果没有理由派生不同的产品,则生成一个公共的父类。这也将生成器模式与抽象工厂模式区分开来,抽象工厂模式创建从公共类型派生的对象。
发件人:http://www.oodesign.com/builder-pattern.html
构建器设计模式描述了一个对象,该对象知道如何在几个步骤中创建另一个特定类型的对象。它在每个中间步骤保持目标项所需的状态。想想StringBuilder是如何生成最终字符串的。
工厂设计模式描述了一个对象,该对象知道如何在一个步骤中创建几种不同但相关的对象,其中特定类型是基于给定参数选择的。想想串行化系统,在这里创建串行化器,它在一次加载调用中构造所需的in对象。
我可以看出建筑商和工厂之间的一个显著区别是
假设我们有一辆车
class Car
{
bool HasGPS;
bool IsCityCar;
bool IsSportsCar;
int Cylenders;
int Seats;
public:
void Car(bool hasGPs=false,bool IsCityCar=false,bool IsSportsCar=false, int Cylender=2, int Seats=4);
};
在上面的界面中,我们可以通过以下方式获取汽车:
int main()
{
BadCar = new Car(false,false,true,4,4);
}
但是如果在创建Seats时发生了一些异常呢???你根本得不到这个物体//但是
假设您有如下实现
class Car
{
bool mHasGPS;
bool mIsCityCar;
bool mIsSportsCar;
int mCylenders;
int mSeats;
public:
void Car() : mHasGPs(false), mIsCityCar(false), mIsSportsCar(false), mCylender(2), mSeats(4) {}
void SetGPS(bool hasGPs=false) {mHasGPs = hasGPs;}
void SetCity(bool CityCar) {mIsCityCar = CityCar;}
void SetSports(bool SportsCar) {mIsSportsCar = SportsCar;}
void SetCylender(int Cylender) {mCylenders = Cylender;}
void SetSeats(int seat) {mSeats = seat;}
};
class CarBuilder
{
Car* mCar;
public:
CarBuilder():mCar(NULL) { mCar* = new Car(); }
~CarBuilder() { if(mCar) { delete mCar; }
Car* GetCar() { return mCar; mCar=new Car(); }
CarBuilder* SetSeats(int n) { mCar->SetSeats(n); return this; }
CarBuilder* SetCylender(int n) { mCar->SetCylender(n); return this; }
CarBuilder* SetSports(bool val) { mCar->SetSports(val); return this; }
CarBuilder* SetCity(bool val) { mCar->SetCity(val); return this; }
CarBuilder* SetGPS(bool val) { mCar->SetGPS(val); return this; }
}
现在您可以这样创建
int main()
{
CarBuilder* bp =new CarBuilder;
Car* NewCar = bp->SetSeats(4)->SetSports(4)->SetCity(ture)->SetGPS(false)->SetSports(true)->GetCar();
bp->SetSeats(2);
bp->SetSports(4);
bp->SetCity(ture);
bp->SetSports(true)
Car* Car_II= bp->GetCar();
}
在第二种情况下,即使一次操作失败,你仍然可以得到汽车。
可能是这辆车后来不太好用了,但你会有目标的。
因为Factory方法在一次调用中为您提供Car,而Builder则逐个构建。
尽管如此,这取决于哪一位的需要。
工厂模式在运行时创建一个类的具体实现,即它的主要目的是使用多态性来允许子类决定实例化哪个类。这意味着在编译时我们不知道将要创建的确切类,而Builder模式主要涉及解决伸缩构造函数反模式的问题,这是由于类的大量可选字段而产生的。在构建器模式中,没有多态性的概念,因为我们知道在编译时要构造什么对象。
这两种模式的唯一共同主题是在工厂方法和构建方法后面隐藏构造函数和对象创建,以改进对象构造。
我相信,当您处理相同的代码库和不断变化的需求时,在一定的时间段内,Factory&Builder模式的用法和它们之间的区别可以更容易理解/澄清。
根据我的经验,通常从Factory模式开始,包括两个静态创建者方法,主要隐藏相对复杂的初始化逻辑。随着对象层次结构变得越来越复杂(或添加更多类型、参数),您可能最终会使用更多参数填充方法,更不用说您必须重新编译Factory模块。所有这些都会增加创建者方法的复杂性,降低可读性,并使创建模块更加脆弱。
该点可能是过渡/延伸点。通过这样做,您可以围绕构造参数创建一个包装器模块,然后您可以通过添加更多抽象(可能)和实现来表示新的(类似的)对象,而无需接触实际的创建逻辑。所以你有了“不那么复杂”的逻辑。
坦率地说,提到某种“一步或多步创建一个对象是不同的”,因为唯一的多样性因素不足以让我区分它们,因为我可以对我目前面临的几乎所有情况都使用这两种方法,而没有任何益处。这就是我最后想到的。