programing tip

Builder Design 패턴과 Factory Design 패턴의 차이점은 무엇입니까?

itbloger 2020. 10. 3. 10:04
반응형

Builder Design 패턴과 Factory Design 패턴의 차이점은 무엇입니까?


Builder 디자인 패턴과 Factory 디자인 패턴의 차이점은 무엇입니까?

어느 것이 더 유리하며 그 이유는 무엇입니까?

이러한 패턴을 테스트하고 비교 / 대조하려면 내 결과를 그래프로 어떻게 표현합니까?


디자인 패턴에는 일반적으로 모든 경우에 작동하는 "더 유리한"솔루션이 없습니다. 구현해야 할 사항에 따라 다릅니다.

Wikipedia에서 :

  • Builder는 복잡한 개체를 단계별로 구성하는 데 중점을 둡니다. Abstract Factory는 제품군 (단순 또는 복합)을 강조합니다. 빌더는 최종 단계로 제품을 반환하지만 Abstract Factory에 관한 한 제품은 즉시 반환됩니다.
  • 빌더는 종종 컴포지트를 빌드합니다.
  • 종종 디자인은 Factory Method를 사용하여 시작하고 (덜 복잡하고, 사용자 정의가 가능하며, 하위 클래스가 확산 됨), 디자이너가 더 많은 유연성이 필요한 곳을 발견함에 따라 Abstract Factory, Prototype 또는 Builder (더 유연하고 복잡함)로 발전합니다.
  • 때로는 생성 패턴이 상호 보완 적입니다. 빌더는 다른 패턴 중 하나를 사용하여 빌드 할 구성 요소를 구현할 수 있습니다. Abstract Factory, Builder 및 Prototype은 구현에서 Singleton을 사용할 수 있습니다.

공장 디자인 패턴에 대한 Wikipedia 항목 : http://en.wikipedia.org/wiki/Factory_method_pattern

빌더 디자인 패턴에 대한 Wikipedia 항목 : http://en.wikipedia.org/wiki/Builder_pattern


팩토리 는 단순히 생성자를 둘러싼 래퍼 함수입니다 (아마도 다른 클래스에있는 것). 주요 차이점은 팩토리 메서드 패턴은 모든 매개 변수가 한 줄로 전달되는 단일 메서드 호출로 전체 개체를 빌드해야한다는 것입니다. 최종 개체가 반환됩니다.

반면 빌더 패턴 은 본질적으로 생성자 호출에 전달할 수있는 모든 가능한 매개 변수를 둘러싼 래퍼 객체입니다. 이렇게하면 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_pattern
http://en.wikipedia.org/wiki/Builder_pattern


Factory 패턴은 Builder 패턴의 단순화 된 버전으로 거의 볼 수 있습니다.

Factory 패턴 에서 Factory 는 필요에 따라 객체의 다양한 하위 유형을 생성하는 작업을 담당합니다.

팩토리 메소드의 사용자는 해당 객체의 정확한 하위 유형을 알 필요가 없습니다. 팩토리 메서드의 예는 또는 형식화 된 개체를 createCar반환 할 수 있습니다 .FordHonda

에서 빌더 패턴, 다른 아형은 작성기 방법으로 만들지 만, 물체의 조성물은 같은 서브 클래스 내에서 다를 수있다.

자동차 예제를 계속하려면 4 기통 엔진으로 유형이 지정된 개체 또는 6 기통이 있는 유형 createCarHonda지정된 개체 를 만드는 빌더 메서드 가있을 수 있습니다 Honda. 빌더 패턴은 이러한 세분화를 허용합니다.

빌더 패턴팩토리 메소드 패턴 의 다이어그램은 Wikipedia에서 사용할 수 있습니다.


빌더 디자인 패턴은 여러 단계에 걸쳐 특정 유형의 다른 개체를 만드는 방법을 알고있는 개체를 설명합니다. 각 중간 단계에서 대상 항목에 필요한 상태를 보유합니다. StringBuilder가 최종 문자열을 생성하는 과정을 생각해보십시오.

팩토리 디자인 패턴은 특정 유형이 주어진 매개 변수에 따라 선택되는 한 단계에서 여러 종류의 서로 다르지만 관련된 객체를 만드는 방법을 알고있는 객체를 설명합니다. serializer를 만들고 한 번의로드 호출에서 원하는 개체를 모두 구성하는 serialization 시스템을 생각해보십시오.


  • 단계별로 복잡한 개체 구성 : 빌더 패턴

  • 하나의 방법으로 간단한 객체 생성 : 팩토리 방법 패턴

  • 다중 팩토리 방식을 이용한 객체 생성 : 추상 팩토리 패턴


둘 다 객체를 만드는 창조 패턴입니다.

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.

Builder Pattern과 Factory 패턴은 둘 다 당신을 위해 객체를 생성하기 때문에 육안으로 꽤 비슷해 보입니다.

하지만 당신은 더 가까이 볼 필요가 있습니다

이 실제 사례는 둘 사이의 차이를 더 분명하게 만들 것입니다.

패스트 푸드 식당에 가서 Food 를 주문했다고 가정 해 보겠습니다 .

1) 어떤 음식?

피자

2) 어떤 토핑?

고추, 토마토, BBQ 치킨, 파인애플 없음

그래서 다른 종류의 음식은 Factory 패턴에 의해 만들어 지지만 특정 음식의 다른 변형 (맛)은 Builder 패턴에 의해 만들어집니다.

다양한 종류의 음식

피자, 버거, 파스타

피자의 변형

치즈, 치즈 + 토마토 + 고추, 치즈 + 토마토 등

코드 샘플

여기에서 두 패턴의 샘플 코드 구현을 볼 수 있습니다.
Builder Pattern
Factory Pattern


먼저 내 주장을 따라야 할 몇 가지 일반적인 사항 :

대형 소프트웨어 시스템을 설계 할 때의 주요 과제는 유연하고 복잡하지 않아야 변경이 가능하다는 것입니다. 이러한 이유로 결합 및 응집력과 같은 몇 가지 메트릭이 있습니다. 전체 시스템을 처음부터 다시 설계 할 필요없이 기능을 쉽게 변경하거나 확장 할 수있는 시스템을 구현하려면 설계 원칙 (SOLID 등)을 따를 수 있습니다. 잠시 후 일부 개발자는 이러한 원칙을 따르면 유사한 문제에 잘 작동하는 유사한 솔루션이 있음을 인식했습니다. 이러한 표준 솔루션은 디자인 패턴으로 밝혀졌습니다.

따라서 디자인 패턴은 높은 응집력으로 느슨하게 결합 된 시스템을 달성하기 위해 일반적인 디자인 원칙을 따르도록 지원하는 것입니다.

질문에 답하기 :

두 패턴의 차이를 물어 보면 어떤 패턴이 시스템을 더 유연하게 만드는지 스스로에게 물어봐야합니다. 각 패턴에는 시스템의 클래스 간 종속성을 구성하는 고유 한 목적이 있습니다.

추상 팩토리 패턴 : GoF : "구체적인 클래스를 지정하지 않고 관련되거나 종속 된 객체의 패밀리를 생성하기위한 인터페이스를 제공합니다."

의미 : 이와 같은 인터페이스를 제공함으로써 각 제품군의 제품 생성자에 대한 호출이 팩토리 클래스에 캡슐화됩니다. 그리고 이것이 전체 시스템에서 이러한 생성자가 호출되는 유일한 장소이기 때문에 새로운 팩토리 클래스를 구현하여 시스템을 변경할 수 있습니다. 다른 공장을 통해 공장 표현을 교환하면 대부분의 코드를 건드리지 않고도 전체 제품 세트를 교환 할 수 있습니다.

빌더 패턴 : GoF : "복잡한 개체의 구성을 표현에서 분리하여 동일한 구성 프로세스가 다른 표현을 만들 수 있도록합니다."

이것이 의미하는 바 : 디렉터 (GoF)라는 다른 클래스의 구성 프로세스를 캡슐화합니다. 이 디렉터에는 제품의 새 인스턴스를 만드는 알고리즘이 포함되어 있습니다 (예 : 다른 부분에서 복잡한 제품 구성). 전체 제품의 필수 부분을 만들기 위해 감독은 빌더를 사용합니다. 디렉터에서 빌더를 교환하면 동일한 알고리즘을 사용하여 제품을 만들 수 있지만 단일 부품의 표현 (따라서 제품의 표현)을 변경할 수 있습니다. 제품 표현에서 시스템을 확장하거나 수정하려면 새 빌더 클래스를 구현하기 만하면됩니다.

요약하자면 Abstract Factory Pattern의 목적은 함께 사용되도록 만들어진 제품 세트를 교환하는 것입니다. Builder Pattern의 목적은 제품을 생성하는 추상 알고리즘을 캡슐화하여 제품의 다양한 표현에 재사용하는 것입니다.

제 생각에는 Abstract Factory Pattern이 Builder Pattern의 큰 형제라고 말할 수 없습니다. 예, 둘 다 창조 패턴이지만 패턴의 주요 의도는 완전히 다릅니다.


Builder와 Factory의 현저한 차이점은 다음과 같습니다.

우리가 차를 가지고 있다고 가정

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);
  }

하지만 좌석을 만드는 동안 예외가 발생하면 어떻게됩니까? 당신은 물체를 전혀 얻지 못할 것입니다 //하지만

다음과 같은 구현이 있다고 가정합니다.

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();

  }

Here in the second case , even if one operation fails you would still get the Car.

May be that car does not works perfectly later but , you would have the object.

Because Factory Method gives you the Car in single call , whereas the Builder builds one by one.

Although, It depends on the needs of the deign which one to go for.


+-------------------------------------------------------------------+---------------------------------------------------+
|                              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                           |
+-------------------------------------------------------------------+---------------------------------------------------+  

Telescoping Constructor Pattern

Analogy:

  • Factory: Consider a restaurant. The creation of "today's meal" is a factory pattern, because you tell the kitchen "get me today's meal" and the kitchen (factory) decides what object to generate, based on hidden criteria.
  • Builder: The builder appears if you order a custom pizza. In this case, the waiter tells the chef (builder) "I need a pizza; add cheese, onions and bacon to it!" Thus, the builder exposes the attributes the generated object should have, but hides how to set them.

Courtesy


Builder and Abstract Factory have meant for different purposes. Depending on right use case, you have to select suitable design pattern.

Builder salient features:

  1. Builder pattern builds a complex object using simple objects and using a step by step approach
  2. A Builder class builds the final object step by step. This builder is independent of other objects
  3. Replacement to Factory method/Abstract Factory in this scenario : Too Many arguments to pass from client program to the Factory class that can be error prone
  4. Some of the parameters might be optional unlike in Factory which forces to send all parameters

Factory (simple Factory) salient features:

  1. Creational pattern
  2. Based on inheritance
  3. Factory returns a Factory Method (interface) which in turn returns Concrete Object
  4. You can substitute new Concrete Objects for interface and client (caller) should not be aware of all concrete implementations
  5. Client always access interface only and you can hide object creation details in Factory method.

Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex)

Have a look at related posts:

Keeping builder in separate class (fluent interface)

Design Patterns: Factory vs Factory method vs Abstract Factory

You can refer to below articles for more details:

sourcemaking

journaldev


Abstract Factory & Builder pattern are both Creational patterns but with different intent.

Abstract Factory Pattern emphasizes object creation for families of related objects where:

  • Each family is a set of classes derived from a common base class/Interface.
  • Each object is returned immediately as a result of one call.

Builder pattern focuses on constructing a complex object step by step. It decouples the representation from the process of constructing the complex object, so that the same construction process can be used for different representations.

  • Builder object encapsulates configuration of the complex object.
  • Director object knows the protocol of using the Builder, where the protocol defines all logical steps required to build the complex object.

Factory: Used for creating an instance of an object where the dependencies of the object are entirely held by the factory. For the abstract factory pattern, there are often many concrete implementations of the same abstract factory. The right implementation of the factory is injected via dependency injection.

Builder: Used to build immutable objects, when the dependencies of the object to be instantiated are partly known in advance and partly provided by the client of the builder.


A complex construction is when the object to be constructed is composed of different other objects which are represented by abstractions.

Consider a menu in McDonald's. A menu contains a drink, a main and a side. Depending on which descendants of the individual abstractions are composed together, the created menu has another representation.

  1. Example: Cola, Big Mac, French Fries
  2. Example: Sprite, Nuggets, Curly Fries

There, we got two instances of the menu with different representations. The process of construction in turn remains the same. You create a menu with a drink, a main and a side.

By using the builder pattern, you separate the algorithm of creating a complex object from the different components used to create it.

In terms of the builder pattern, the algorithm is encapsulated in the director whereas the builders are used to create the integral parts. Varying the used builder in the algorithm of the director results in a different representation because other parts are composed to a menu. The way a menu is created remains the same.


Difference is clear In builder pattern, builder will create specific type of object for you. You have to tell what builder has to build. In factory pattern , using abstract class you are directly building the specific object.

Here builder class acts as mediator between main class and specific type classes. More abstraction.


Both are very much similar , but if you have a large number of parameters for object creation with some of them optional with some default values , go for Builder pattern.


I believe, the usage of and the difference between Factory & Builder patterns can be understood/clarified easier in a certain time period as you worked on the same code base and changing requirements.

From my experience, usually, you start with a Factory pattern including couple of static creator methods. As your object hierarchy gets more complex (or as you add more types), you probably end up with having your methods populated with more parameters and not to mention you gonna have to recompile your Factory module. All those stuff, increases the complexity of your creator methods, decreases the readability and makes the creation module more fragile.

This point possibly will be the transition point. Transition from Factory to Builder pattern. By doing so, you create a wrapper module around the construction parameters and then you will be able represent new (similar) objects by adding some more abstractions(perhaps) and implementations without touching actual your creation logic. So you've had less complex logic and re-compiled source code

Frankly, referring to something sort of "having an object created in one-step or multiple steps is the difference" as the sole diversity factor was not sufficient for me to distinguish them since I could use both ways for almost all cases I faced up to now without experiencing any benefit. So this is what I've finally thought about it.


The main difference between them is that the Builder pattern primarily describes the creation of complex objects step by step. In the Abstract Factory pattern, the emphasis is on families of objects-products. Builder returns the product in the last step. While in the Abstract Factory pattern the product is available immediately.

Example: Let say that we are creating Maze

1. Abstract Factory:

Maze* MazeGame::CreateMaze (MazeFactory& factory) {
Maze* maze = factory.MakeMaze(); /// product is available at start!!
 /* Call some methods on maze */
return maze;
}

2. Builder:

Maze* MazeGame::CreateMaze (MazeBuilder& builder) {
builder.buildMaze(); /// We don't have access to maze
 /* Call some methods on builder */
return builder.GetMaze();
}

Build pattern emphasizes on complexity of creating object (solved by "steps")

Abstract pattern emphasizes "just" on "abstraction" of (multiple but related) objects.


In my opinion Builder pattern is used when you want to create an object from a bunch of other objects and creation of part needs to be independent of the object you want to create. It helps to hide the creation of part from the client to make builder and client independent. It is used for complex objects creation (objects which may consists of complicated properties)

While factory pattern specifies that you want to create objects of a common family and you want it to be cerated at once. It is used for simpler objects.


IMHO

Builder is some kind of more complex Factory.

But in Builder you can instantiate objects with using another factories, that are required to build final and valid object.

So, talking about "Creational Patterns" evolution by complexity you can think about it in this way:

Dependency Injection Container -> Service Locator -> Builder -> Factory

Builder and Abstract Factory

The Builder design pattern is very similar, at some extent, to the Abstract Factory pattern. That's why it is important to be able to make the difference between the situations when one or the other is used. In the case of the Abstract Factory, the client uses the factory's methods to create its own objects. In the Builder's case, the Builder class is instructed on how to create the object and then it is asked for it, but the way that the class is put together is up to the Builder class, this detail making the difference between the two patterns.

Common interface for products

In practice the products created by the concrete builders have a structure significantly different, so if there is not a reason to derive different products a common parent class. This also distinguishes the Builder pattern from the Abstract Factory pattern which creates objects derived from a common type.

From: http://www.oodesign.com/builder-pattern.html


Both patterns come for the same necessity: Hide from some client code the construction logic of a complex object. But what makes "complex" (or, sometimes, complicate) an object? Mainly, it's due to dependencies, or rather the state of an object composed by more partial states. You can inject dependencies by constructor to set the initial object state, but an object may require a lot of them, some will be in a default initial state (just because we should have learned that set a default dependency to null is not the cleanest way) and some other set to a state driven by some condition. Moreover, there are object properties that are some kind of "oblivious dependencies" but also they can assume optional states.

there are two well known ways to dominate that complexity:

  • Composition/aggregation: Construct an object, construct its dependent objects, then wire together. Here, a builder can make transparent and flexible the process that determines the rules that lead the construction of component.

  • Polymorphism: Construction rules are declared directly into subtype definition, so you have a set of rules for each subtype and some condition decides which one among these set of rules apply to construct the object. A factory fits perfectly in this scenario.

Nothing prevents to mix these two approaches. A family of product could abstract object creation done with a builder, a builder could use factories to determine which component object instantiate.


Factory pattern creates a concrete implementation of a class at runtime, i.e its main intention is to use polymorphism to allow subclasses decide which class to instantiate. This means at compile time we dont know the exact class that will be created, while Builder pattern is mainly concerned with solving the problem of telescoping constructors antipattern, which arises due to a large number of optional fields of a class. In builder pattern there is no notion of polymorphism, as we know what object we are trying to construct at compile time.

The only common theme of these two patterns is the hiding of constructors and object creation behind factory methods, and the build method, for improved object construction.


Factory pattern let you create an object at once at once while builder pattern let you break the creation process of an object. In this way, you can add different functionality during the creation of an object.

참고URL : https://stackoverflow.com/questions/757743/what-is-the-difference-between-builder-design-pattern-and-factory-design-pattern

반응형