【问题标题】:What is the difference between Builder Design pattern and Factory Design pattern? [closed]建造者设计模式和工厂设计模式有什么区别? [关闭]
【发布时间】:2010-10-19 22:54:57
【问题描述】:

建造者设计模式和工厂设计模式有什么区别?

哪个更有利,为什么?

如果我想测试和比较/对比这些模式,如何将我的发现表示为图表?

【问题讨论】:

  • 既然他们做的事情不同,那么“优势”是什么意思?
  • Builderconstructor 的更复杂版本 - 而 factory method 是简化版本。
  • @DávidHorváth 我不会将 Builder 描述为“更复杂”。当你处理一个有 100 个参数的构造函数时,你只关心其中的 3 个,而且你知道参数的数量将来可能会改变,使用 Builder 模式会让每个人的生活变得更简单。
  • @Aberrant 复杂的使用和架构的复杂性是两个不同的东西。我专注于后者。

标签: design-patterns factory-pattern factory-method builder-pattern


【解决方案1】:

对于设计模式,通常没有适用于所有情况的“更有利”的解决方案。这取决于您需要实现什么。

来自*:

  • Builder 专注于构建一个 复杂的对象一步一步。抽象的 工厂强调产品家族 对象(简单或复杂)。 Builder 将产品作为最终产品返回 一步,但就摘要而言 工厂方面,产品得到 立即返回。
  • Builder 通常会构建 Composite。
  • 通常,设计开始时使用工厂方法(不太复杂,更多 可定制,子类激增) 并向抽象工厂发展, 原型或构建器(更灵活, 更复杂)作为设计师 发现更灵活的地方 需要。
  • 有时创建模式是互补的:构建器可以使用一个 要实现的其他模式 构建了哪些组件。抽象的 Factory、Builder 和 Prototype 可以 在他们的中使用 Singleton 实现。

工厂设计模式的*条目: http://en.wikipedia.org/wiki/Factory_method_pattern

构建器设计模式的*条目: http://en.wikipedia.org/wiki/Builder_pattern

【讨论】:

  • 这正是不同之处。仅当无法一步生成对象时才需要构建器。一个很好的例子是复杂对象的反序列化过程。很多时候复杂对象的参数必须一一检索。
  • 对于第一句话,我想说绝对有一个更有利的解决方案可以广泛应用......我们只是看不到这些,因为它们最终直接融入了编程语言。跨度>
  • @Joel:我同意某些模式比其他模式更常见(例如,Factory 似乎比 Builder 更常见),但我的意思是它们中没有一个总是比另一个更好,无论场景如何。
  • 很好的答案,虽然有两件事值得添加:1) Builder 主要用于使用 Fluent API 构建 POJO(例如 Person.builder().withName("Sam").withAge(38 ).build(). 2) 在我的经验中,builder 对于域对象的 POJO 创建很有用,而 factory 对于创建像 PdfGeneratorFactory 类这样的服务对象很有用。服务对象可以在工厂中缓存超过 1 次使用,而 builder 总是按设计创建一个新对象。
  • 这个答案所做的就是重复维基。它没有增加任何东西。需要自己的话来解释差异是什么。
【解决方案2】:

工厂 只是构造函数(可能在不同类中的构造函数)的包装函数。关键区别在于工厂方法模式要求整个对象在单个方法调用中构建,所有参数都在一行中传入。最终的对象将被返回。

另一方面,

构建器模式本质上是一个包装器对象,包含您可能希望传递给构造器调用的所有可能参数。这允许您使用 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

【讨论】:

  • 这不是构建器模式 imo 的正确用法,即使在您粘贴的 wiki 链接中,用法也不同。这个 FruitBuilder 是 Director 和 Builder 组件的某种组合,您可以在其中调用 build() 应该属于 Director 和 setter 属于 Builder 组件。 Director 应包含有关如何使用 Builders 方法创建对象的业务逻辑。 Fluent api 不是构建器模式,StringBuilder 也不是构建器模式。
  • 有两种不同的模式通常被称为“builder”:a) builder 根据 Erich 的“设计模式:可重用的面向对象软件的元素” Gamma、Richard Helm、Ralph Johnson 和 John Vlissides --- b) 构建器,根据 Joshua Bloch 的“Effective Java”。 “当面临许多构造函数参数时,请考虑使用构建器。”此模式使用method cascading / fluent interface 来初始化(不可变)具有大量属性的对象。
【解决方案3】:

工厂模式几乎可以看作是建造者模式的简化版。

工厂模式中,工厂负责根据需要创建对象的各种子类型。

工厂方法的用户不需要知道该对象的确切子类型。工厂方法 createCar 的示例可能会返回 FordHonda 类型的对象。

Builder 模式中,不同的子类型也由 builder 方法创建,但同一子类中对象的组成可能不同。

继续汽车示例,您可能有一个 createCar 构建器方法,该方法创建一个具有 4 缸发动机的 Honda 类型对象,或一个具有 6 个气缸的 Honda 类型对象。构建器模式允许这种更精细的粒度。

Builder patternFactory method pattern 的图表可在 Wikipedia 上找到。

【讨论】:

  • 建造者模式就像放大到大物体的建造。大对象由其他对象组成,这些对象像递归一样进一步组成。工厂只需一个电话即可为您提供所需的东西。这种理解正确吗?
【解决方案4】:

构建器设计模式描述了一个对象,该对象知道如何通过几个步骤制作另一个特定类型的对象。它在每个中间步骤保持目标项目所需的状态。想想 StringBuilder 生成最终字符串的过程。

工厂设计模式描述了一个对象,它知道如何一步创建几种不同但相关的对象,其中特定类型是根据给定的参数选择的。想想序列化系统,您可以在其中创建序列化程序并在一次加载调用中构建所需的 in 对象。

【讨论】:

  • 只是一些提示:构建器模式的好例子是“流利的接口”,而 ADO.NET 充满了“工厂”和“抽象工厂”实现(即 DbFactory)。
【解决方案5】:
  • 逐步构建复杂对象:构建器模式

  • 使用单一方法创建一个简单的对象:工厂方法模式

  • 使用多工厂方法创建对象:抽象工厂模式

【讨论】:

    【解决方案6】:

    Builder Pattern 和 Factory Pattern,两者看起来都非常类似于肉眼,因为它们都为您创建对象。

    但你需要仔细观察

    这个现实生活中的例子将使两者之间的区别更加清晰。

    假设,您去一家快餐店点了食物

    1) 什么食物?

    披萨

    2) 什么浇头?

    辣椒、番茄、烤鸡、无菠萝

    所以不同种类的食物是由工厂模式制造的,但特定食物的不同变体(口味)是由建造者模式制造的。

    不同种类的食物

    比萨、汉堡、意大利面

    披萨的变种

    只有芝士、芝士+番茄+辣椒、芝士+番茄等。

    代码示例

    您可以在此处查看两种模式的示例代码实现
    Builder Pattern
    Factory Pattern

    【讨论】:

    • 感谢您提供示例代码!您的示例很好地区分了这两种模式。
    【解决方案7】:

    两者都是创建模式,用于创建对象。

    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.
    

    【讨论】:

      【解决方案8】:
      Builder Factory
      Return only single instance to handle complex object construction Return various instances on multiple constructors
      No interface required Interface driven
      Inner classes is involved (to avoid telescopic constructors) Subclasses are involved

      Telescoping Constructor Pattern

      类比:

      • 工厂:考虑一家餐馆。 “今天的饭菜”的创建是一种工厂模式,因为你告诉厨房“给我今天的饭菜”,厨房(工厂)根据隐藏的标准决定生成什么对象。
      • 构建器:如果您订购定制披萨,构建器就会出现。在这种情况下,服务员告诉厨师(建造者)“我需要一个比萨饼;加奶酪、洋葱和培根!”因此,构建器公开了生成的对象应具有的属性,但隐藏了如何设置它们。

      Courtesy

      【讨论】:

        【解决方案9】:

        首先要遵循我的论点:

        设计大型软件系统的主要挑战是它们必须灵活且易于更改。出于这个原因,有一些指标,如耦合和内聚。为了实现可以轻松更改或扩展其功能而不需要从头开始重新设计整个系统的系统,您可以遵循设计原则(如 SOLID 等)。一段时间后,一些开发人员意识到,如果他们遵循这些原则,就会有一些类似的解决方案可以很好地解决类似的问题。这些标准解决方案最终成为了设计模式。

        因此,设计模式是为了支持您遵循一般设计原则,以实现具有高内聚性的松散耦合系统。

        回答问题:

        通过询问两种模式之间的区别,您必须问自己哪种模式使您的系统以哪种方式更灵活。每种模式都有自己的目的来组织系统中类之间的依赖关系。

        抽象工厂模式: GoF:“为创建相关或依赖对象系列提供一个接口,而无需指定它们的具体类。”

        这是什么意思: 通过提供这样的接口,对每个系列产品的构造函数的调用都封装在工厂类中。因为这是整个系统中唯一调用这些构造函数的地方,所以您可以通过实现一个新的工厂类来更改您的系统。如果你通过另一个交换工厂的表示,你可以在不接触大部分代码的情况下交换一整套产品。

        建造者模式: GoF:“将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示。”

        这是什么意思: 您将构建过程封装在另一个类中,称为导向器 (GoF)。该导向器包含创建产品新实例的算法(例如,由其他部分组成复杂产品)。为了创建整个产品的组成部分,导演使用了构建器。通过在导向器中交换构建器,您可以使用相同的算法来创建产品,但会更改单个部分的表示(以及产品的表示)。要在产品表示中扩展或修改您的系统,您需要做的就是实现一个新的构建器类。

        简而言之: 抽象工厂模式的目的是交换一组可以一起使用的产品。 Builder Pattern 的目的是封装创建产品的抽象算法,以便将其重用于产品的不同表示。

        在我看来,你不能说抽象工厂模式是建造者模式的老大哥。是的,它们都是创建模式,但模式的主要意图完全不同。

        【讨论】:

        • 很好的答案,详细解释。
        • 你能解释一下“将复杂对象的构造与其表示分开”的含义
        • @Rajdeep 解释是渴望发表评论,这就是我写另一个答案的原因。
        • @Janis 我可以阅读的答案或来源在哪里?
        • @Rajdeep 我建议你阅读《设计模式》这本书 - amazon.de/Patterns-Elements-Reusable-Object-Oriented-Software/…
        【解决方案10】:

        我可以看出 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();
        
          }
        

        在第二种情况下,即使一次操作失败,您仍然可以获得 Car。

        可能是那辆车以后不能完美运行,但是,你会得到这个对象。

        因为工厂方法在单个调用中为您提供 Car,而 Builder 则一个一个地构建。

        虽然,这取决于设计的需要。

        【讨论】:

        • 当然,没有车总比废车好——如果你来利用休息时间才发现问题怎么办?
        • @Ken :我并不是坚持从商业项目等的角度来看它是一个好的设计,而是引用这个例子来举例说明模式之间的差异。毫无疑问,您是正确的,从用户体验来看,这对坏车来说是很糟糕的,但是,考虑到有制造汽车的工厂,并且某些部件出现故障,然后汽车确实会生产出来,但会出现严重的故障,这将在该车的测试和运送给客户的时间已停止。
        • 我想澄清一下,我实际上是构建器模式的忠实粉丝,但是,不是因为你给出的原因。无效的对象应该在构造时失败,越往下发现错误的过程就越昂贵。对于构建器模式,如果缺少任何必需的数据,构建方法(在您的示例中称为 getCar())抛出异常是正常的。
        【解决方案11】:

        工厂:用于创建对象的实例,其中对象的依赖关系完全由工厂持有。对于抽象工厂模式,同一个抽象工厂通常有很多具体的实现。工厂的正确实现是通过依赖注入注入的。

        Builder:用于构建不可变对象,当要实例化的对象的依赖部分是预先知道的,部分是由建设者的客户。

        【讨论】:

          【解决方案12】:

          BuilderAbstract Factory 有不同的用途。根据正确的用例,您必须选择合适的设计模式。

          Builder 显着特点:

          1. 构建器模式使用简单对象并使用分步方法构建复杂对象
          2. Builder 类逐步构建最终对象。此构建器独立于其他对象
          3. 在这种情况下替换为工厂方法/抽象工厂:从客户端程序传递到工厂类的参数过多,容易出错
          4. 某些参数可能是可选的,不像 Factory 中强制发送所有参数

          Factory(简单工厂)的显着特点:

          1. 创作模式
          2. 基于继承
          3. Factory 返回一个工厂方法(接口),该方法又返回具体对象
          4. 您可以用新的具体对象替换接口,客户端(调用者)不应该知道所有具体实现
          5. 客户端始终只访问接口,您可以在工厂方法中隐藏对象创建细节。

          通常,设计开始使用工厂方法(不太复杂,更可定制,子类激增)并朝着抽象工厂原型,或 Builder(更灵活、更复杂)

          查看相关帖子:

          Keeping builder in separate class (fluent interface)

          Design Patterns: Factory vs Factory method vs Abstract Factory

          您可以参考以下文章了解更多详情:

          sourcemaking

          journaldev

          【讨论】:

            【解决方案13】:

            Abstract Factory & Builder 模式都是 Creational 模式,但意图不同。

            抽象工厂模式强调为相关对象系列创建对象,其中:

            • 每个系列都是从公共基类/接口派生的一组类。
            • 每次调用都会立即返回每个对象。

            建造者模式侧重于逐步构建复杂的对象。 它将表示与构造复杂对象的过程解耦,使得相同的构造过程可以用于不同的表示。

            • Builder 对象封装了复杂对象的配置。
            • Director 对象知道使用 Builder 的协议,其中 协议定义了构建复杂对象所需的所有逻辑步骤。

            【讨论】:

            • 你能解释一下“将表示从构造复杂对象的过程中解耦”的意思吗
            【解决方案14】:

            构建器模式相对于工厂模式的主要优势在于,如果您想创建具有许多可能自定义的标准对象,但通常最终只自定义一些。

            例如,如果您想编写一个 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()
            

            如果您为此使用工厂模式,您最终会编写很多方法,其中包含所有可能的创建参数组合。 使用构建器,您只需指定您关心的那些,然后让构建器为您构建它,并处理所有其他参数。

            【讨论】:

              【解决方案15】:

              复杂构造是指要构造的对象由抽象表示的不同其他对象组成。

              考虑一下麦当劳的菜单。菜单包含饮料、主菜和配菜。根据各个抽象的后代组合在一起,创建的菜单具有另一种表示形式。

              1. 示例:可乐、巨无霸、炸薯条
              2. 示例:雪碧、金块、卷曲薯条

              在那里,我们得到了两个具有不同表示形式的菜单实例。反过来,建造过程保持不变。您可以创建一个包含饮料、主菜和配菜的菜单。

              通过使用构建器模式,您可以将创建复杂对象的算法与用于创建它的不同组件分开。

              就构建器模式而言,算法封装在导向器中,而构建器用于创建整体部分。改变导向器算法中使用的构建器会导致不同的表示,因为其他部分组成一个菜单。创建菜单的方式保持不变。

              【讨论】:

              • 这解释了“复杂对象的构造与其表示的分离”
              【解决方案16】:

              它们之间的主要区别在于构建器模式主要描述了逐步创建复杂对象。在抽象工厂模式中,重点是对象-产品系列。 Builder 在最后一步返回产品。在抽象工厂模式中,产品立即可用

              示例: 假设我们正在创建迷宫

              1.抽象工厂:

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

              2。建造者:

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

              【讨论】:

                【解决方案17】:

                这两种模式都有相同的必要性:对某些客户端代码隐藏复杂对象的构造逻辑。但是是什么让一个对象“复杂”(或者,有时,复杂)?主要是由于依赖关系,或者更确切地说是由更多部分状态组成的对象的状态。您可以通过构造函数注入依赖项来设置初始对象状态,但是一个对象可能需要很多依赖项,有些将处于默认初始状态(只是因为我们应该知道将默认依赖项设置为 null 并不是最干净的方法) 和其他一些设置为由某些条件驱动的状态。此外,有些对象属性是某种“不经意的依赖关系”,但它们也可以假定为可选状态。

                有两种众所周知的方法可以控制这种复杂性:

                • 组合/聚合:构造一个对象,构造它的依赖对象,然后连接在一起。在这里,构建者可以使确定引导组件构建的规则的过程变得透明和灵活。

                • 多态性:构造规则直接声明到子类型定义中,因此您对每个子类型都有一组规则,并且某些条件决定了这些规则中的哪一个适用于构造对象。工厂非常适合这种情况。

                没有什么能阻止混合这两种方法。一个产品系列可以抽象使用构建器完成的对象创建,构建器可以使用工厂来确定实例化哪个组件对象。

                【讨论】:

                  【解决方案18】:

                  我相信,当您处理相同的代码库和不断变化的需求时,可以在特定时间段内更容易地理解/澄清 Factory 和 Builder 模式的用法和区别。

                  根据我的经验,通常,您从包含几个静态创建者方法的工厂模式开始,主要隐藏相对复杂的初始化逻辑。随着您的对象层次结构变得更加复杂(或者随着您添加更多类型、参数),您最终可能会在您的方法中填充更多参数,更不用说您将不得不重新编译您的 Factory 模块。所有这些都增加了创建者方法的复杂性,降低了可读性并使创建模块更加脆弱。

                  这个点可能是过渡/延伸点。通过这样做,您可以围绕 构造参数 创建一个包装器模块,然后您将能够通过添加更多抽象(可能)和实现来表示新的(相似的)对象,而无需触及实际的创建逻辑。所以你有“更少”复杂的逻辑。

                  坦率地说,提到某种“在一步或多个步骤中创建对象是不同的”,因为唯一的多样性因素不足以让我区分它们,因为我几乎可以在所有情况下使用这两种方式我面对现在没有任何好处。所以这就是我最终想到的。

                  【讨论】:

                    【解决方案19】:

                    构建模式强调创建对象的复杂性(通过“步骤”解决)

                    抽象模式强调对(多个但相关的)对象的“抽象”“公正”。

                    【讨论】:

                      【解决方案20】:

                      两者非常相似,但是如果您有大量用于创建对象的参数,其中一些参数是可选的,并带有一些默认值,请选择 Builder 模式。

                      【讨论】:

                        【解决方案21】:

                        恕我直言

                        Builder 是某种更复杂的工厂。

                        在 Builder 中,您可以使用其他工厂实例化对象,这是构建最终和有效对象所必需的。

                        因此,按照复杂性来讨论“创建模式”的演变,您可以这样考虑:

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

                        【讨论】:

                          【解决方案22】:

                          区别很明显 在构建器模式中,构建器将为您创建特定类型的对象。你必须告诉什么 建造者必须建造。 在工厂模式中,使用抽象类直接构建特定对象。

                          这里的builder类充当主类和特定类型类之间的中介。 更抽象。

                          【讨论】:

                            【解决方案23】:

                            在我看来 当您想从一堆其他对象中创建一个对象并且部分的创建需要独立于您要创建的对象时,使用构建器模式。它有助于向客户隐藏零件的创建,以使构建者和客户独立。它用于创建复杂的对象(可能包含复杂属性的对象)

                            虽然工厂模式指定您要创建一个通用系列的对象,并且您希望它立即被创建。它用于更简单的对象。

                            【讨论】:

                              【解决方案24】:

                              生成器和抽象工厂

                              在某种程度上,Builder 设计模式与抽象工厂模式非常相似。这就是为什么在使用其中一种情况时能够区分情况很重要的原因。在抽象工厂的情况下,客户端使用工厂的方法来创建自己的对象。在 Builder 的情况下,Builder 类被指示如何创建对象,然后被要求提供它,但是将类放在一起的方式取决于 Builder 类,这个细节决定了两种模式之间的区别。

                              产品通用接口

                              在实践中,由具体构建者创建的产品具有显着不同的结构,因此如果没有理由派生不同的产品,则可以使用一个共同的父类。这也将 Builder 模式与抽象工厂模式区分开来,后者创建从通用类型派生的对象。

                              发件人:http://www.oodesign.com/builder-pattern.html

                              【讨论】:

                                【解决方案25】:

                                许多设计从使用工厂方法(通过子类更简单且更可定制)开始,然后向抽象工厂原型或Builder(更灵活,但更复杂)。

                                Builder专注于逐步构建复杂的对象。

                                实现它:

                                1. 明确定义构建所有可用产品表示的通用构建步骤。否则,您将无法继续实施该模式。
                                2. 在基础构建器界面中声明这些步骤。
                                3. 为每个产品表示创建一个具体的构建器类并实施它们的构建步骤。

                                Abstract Factory 专注于创建相关对象系列。 Abstract Factory 立即返回产品,而 Builder 允许您在获取产品之前运行一些额外的构建步骤。

                                您可以将 Abstract FactoryBridge 一起使用。当 Bridge 定义的某些抽象只能与特定实现一起使用时,这种配对很有用。在这种情况下,抽象工厂可以封装这些关系并对客户端代码隐藏复杂性。

                                Dive into design pattern

                                【讨论】:

                                  【解决方案26】:

                                  工厂模式在运行时创建一个类的具体实现,即它的主要目的是使用多态性来允许子类决定实例化哪个类。这意味着在编译时我们不知道将创建的确切类,而 Builder 模式主要关注的是解决由于类的大量可选字段而产生的可伸缩构造函数反模式的问题。在构建器模式中没有多态性的概念,因为我们知道在编译时我们试图构建什么对象。

                                  这两种模式的唯一共同主题是在工厂方法和构建方法后面隐藏构造函数和对象创建,以改进对象构造。

                                  【讨论】:

                                    【解决方案27】:

                                    工厂模式让你一次创建一个对象,而建造者模式让你打破一个对象的创建过程。这样,您可以在创建对象期间添加不同的功能。

                                    【讨论】: