Pen*_*uen 609 design-patterns factory-method factory-pattern builder-pattern
Builder设计模式和Factory设计模式有什么区别?
哪一个更有利,为什么?
如果我想测试和比较/对比这些模式,我如何将我的发现表示为图表?
Adr*_*ore 435
对于设计模式,通常没有"更有利"的解决方案适用于所有情况.这取决于您需要实施的内容.
来自维基百科:
- Builder专注于逐步构建复杂对象.Abstract Factory强调一系列产品对象(简单或复杂).Builder将产品作为最后一步返回,但就Abstract Factory而言,产品会立即返回.
- Builder经常构建一个Composite.
- 通常,设计开始使用工厂方法(不太复杂,可定制,子类增加),并逐渐向抽象工厂,原型或构建器(更灵活,更复杂)发展,因为设计师发现需要更多灵活性的地方.
- 有时创建模式是互补的:Builder可以使用其他模式之一来实现构建哪些组件.Abstract Factory,Builder和Prototype可以在其实现中使用Singleton.
工厂设计模式的维基百科条目:http: //en.wikipedia.org/wiki/Factory_method_pattern
建筑师设计模式的维基百科条目:http: //en.wikipedia.org/wiki/Builder_pattern
Jam*_*gan 318
工厂只是构造函数(可能是不同类中的一个)的包装函数.关键区别在于工厂方法模式要求在单个方法调用中构建整个对象,所有参数都在一行中传递.将返回最终对象.
另一方面,构建器模式实质上是围绕可能要传递给构造函数调用的所有可能参数的包装器对象.这允许您使用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");
Run Code Online (Sandbox Code Playgroud)
基本构建器示例
// 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();
Run Code Online (Sandbox Code Playgroud)
可能值得比较来自这两个维基百科页面的代码示例:
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Builder_pattern
Ben*_*n S 272
Factory模式几乎可以看作是Builder模式的简化版本.
在工厂模式中,工厂负责根据需要创建对象的各种子类型.
工厂方法的用户不需要知道该对象的确切子类型.工厂方法的示例createCar可能返回一个Ford或一个Honda类型化的对象.
在Builder模式中,构造方法也会创建不同的子类型,但对象的组成可能在同一个子类中有所不同.
要继续汽车示例,您可能有一个createCar构建器方法,该方法Honda使用4柱面引擎或Honda具有6个柱面的对象创建对象.构建器模式允许更精细的粒度.
维基百科上提供了Builder模式和Factory方法模式的图表.
Joe*_*orn 58
构建器设计模式描述了一个对象,该对象知道如何通过几个步骤制作特定类型的另一个对象.它在每个中间步骤保持目标项的所需状态.想想StringBuilder通过什么来生成最终字符串.
工厂设计模式描述了一个对象,该对象知道如何在一个步骤中创建多个不同但相关的对象,其中基于给定参数选择特定类型.想想序列化系统,您可以在其中创建序列化程序,并在一次加载调用中构建所需的对象.
Ton*_*ony 16
两者都是Creational模式,用于创建Object.
1)工厂模式 - 假设您有一个超类和N个子类.创建对象取决于传递的参数/值.
2)构建器模式 - 创建复杂对象.
Ex: Make a Loan Object. Loan could be house loan, car loan ,
education loan ..etc. Each loan will have different interest rate, amount ,
duration ...etc. Finally a complex object created through step by step process.
Run Code Online (Sandbox Code Playgroud)
Roh*_*ngh 16
生成器模式和工厂模式,看起来都非常类似于肉眼,因为它们都为您创建对象.
这个现实生活中的例子将使两者之间的区别更加清晰.
假设,你去了一家快餐店订购了食品.
比萨
辣椒,番茄,烧烤鸡,没有菠萝
因此,不同种类的食物是由工厂模式制作的,但特定食物的不同变体(风味)是由Builder模式制作的.
不同种类的食物
比萨饼,汉堡,意大利面
比萨的变种
只有奶酪,奶酪+番茄+辣椒,奶酪+番茄等.
您可以在此处查看
Builder Pattern Factory Pattern的两种模式的示例代码实现
Jan*_*nis 12
首先是一些关于我的论证的一般性事项:
设计大型软件系统的主要挑战是它们必须灵活且不易变化.出于这个原因,有一些指标,如耦合和内聚.要实现易于更改或扩展其功能而无需从头开始重新设计整个系统的系统,您可以遵循设计原则(如SOLID等).一段时间后,一些开发人员认识到,如果他们遵循这些原则,那么有一些类似的解决方 这些标准解决方案被证明是设计模式.
因此,设计模式是为了支持您遵循一般设计原则,以实现具有高内聚力的松散耦合系统.
回答这个问题:
通过询问两种模式之间的区别,您必须问自己哪种模式可以使您的系统更灵活.每个模式都有自己的目的,即组织系统中各类之间的依赖关系.
抽象工厂模式: GoF:"提供一个接口,用于创建相关或依赖对象的族,而无需指定其具体类."
这意味着什么: 通过提供这样的接口,对每个系列产品的构造函数的调用被封装在工厂类中.因为这是整个系统中唯一一个调用这些构造函数的地方,你可以通过实现一个新的工厂类来改变你的系统.如果您通过另一个交换工厂的代表,您可以交换一整套产品而无需接触大部分代码.
构建器模式: GoF:"将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的表示."
这意味着什么: 你将构造过程封装在另一个类中,称为导演(GoF).该导演包含创建产品新实例的算法(例如,从其他部分组成复杂的产品).为了创建整个产品的组成部分,导演使用了一个建筑师.通过在导向器中交换构建器,您可以使用相同的算法来创建产品,但更改单个部件的表示(以及产品的表示).要在产品表示中扩展或修改系统,您需要做的就是实现一个新的构建器类.
简而言之: 抽象工厂模式的目的是交换一组可以一起使用的产品.Builder Pattern的目的是封装创建产品的抽象算法,以便将其重用于产品的不同表示.
在我看来,你不能说抽象工厂模式是Builder模式的大哥.是的,它们都是创作模式,但模式的主要意图完全不同.
建造者和工厂之间的一个显着区别我可以得出如下
假设我们有车
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);
};
Run Code Online (Sandbox Code Playgroud)
在上面的界面中我们可以通过以下方式获得汽车:
int main()
{
BadCar = new Car(false,false,true,4,4);
}
Run Code Online (Sandbox Code Playgroud)
但是如果在创建座位时发生了一些异常呢?你不会全部获得对象//但是
假设你有如下的实现
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; }
}
Run Code Online (Sandbox Code Playgroud)
现在你可以像这样创建
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();
}
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,即使一次操作失败,您仍然可以获得汽车.
可能是那辆车以后不能很好地工作但是,你会有这个对象.
因为Factory Method会在单次调用中为您提供Car,而Builder会逐个构建.
虽然,这取决于设计的需要.
+-------------------------------------------------------------------+---------------------------------------------------+
| Builder | Factory |
+-------------------------------------------------------------------+---------------------------------------------------+
| Return only single instance to handle complex object construction | Retrun various instances on multiple constructors |
| No interface required | Interface driven |
| Inner classes is involved (to avoid telescopic constructors) | Subclasses are involved |
+-------------------------------------------------------------------+---------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
比喻:
工厂:用于创建对象的实例,其中对象的依赖项完全由工厂持有。对于抽象工厂模式,同一个抽象工厂往往有很多具体的实现。工厂的正确实现是通过依赖注入注入的。
Builder : 用于构建不可变对象,当要实例化的对象的依赖部分预先已知,部分由构建器的客户端提供时。
生成器和抽象工厂的含义不同。根据正确的用例,您必须选择合适的设计模式。
生成器的主要功能:
工厂(简单工厂)的主要特点:
通常,设计从使用Factory方法开始(不那么复杂,更可定制,子类激增),然后演变为Abstract Factory,Prototype或Builder(更灵活,更复杂)
看一下相关帖子:
您可以参考以下文章以了解更多详细信息:
与工厂模式相比,构建器模式的主要优点是,如果您想要创建一些具有大量可能的自定义项的标准对象,但您通常最终只会自定义其中一些。
例如,如果您想编写一个 HTTP 客户端 - 您将设置一些默认参数,例如默认写入/读取超时、协议、缓存、DNS、拦截器等。
您的客户端的大多数用户只会使用这些默认参数,而其他一些用户可能想要自定义一些其他参数。在某些情况下,您只想更改超时并按原样使用其余部分,而在其他情况下,您可能需要自定义例如缓存。
以下是实例化客户端的可能方法(取自 OkHttpClient):
//just give me the default stuff
HttpClient.Builder().build()
//I want to use custom cache
HttpClient.Builder().cache(MyCache()).build()
//I want custom connection timeout
HttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).build()
//I am more interested in read/write timeout
HttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS).build()
Run Code Online (Sandbox Code Playgroud)
如果您为此使用工厂模式,您最终将编写大量具有所有可能的创建参数组合的方法。使用构建器,您只需指定您关心的参数,然后让构建器为您构建它,并处理所有其他参数。