首页 文章

Builder Design模式和Factory Design模式有什么区别?

提问于
浏览
506

Builder设计模式和Factory设计模式有什么区别?

哪一个更有利,为什么?

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

26 回答

  • 0

    两者都是Creational模式,用于创建Object .

    1)工厂模式 - 假设您有一个超类和N个子类 . 创建对象取决于传递的参数/值 .

    2)Builder模式 - 创建复杂对象 .

    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.
    
  • -3

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

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

  • 1

    工厂模式允许您一次创建一个对象,而构建器模式可以让您打破对象的创建过程 . 通过这种方式,您可以在创建对象期间添加不同的功能 .

  • 0
    +-------------------------------------------------------------------+---------------------------------------------------+
    |                              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: 考虑一家餐馆 . "today's meal"的创建是工厂模式,因为您告诉厨房"get me today's meal"并且厨房(工厂)根据隐藏的标准决定要生成什么对象 .

    • Builder: 如果您订购自定义披萨,则会显示构建器 . 在这种情况下,服务员告诉大厨(构建器)"I need a pizza; add cheese, onions and bacon to it!"因此,构建器公开生成的对象应具有的属性,但隐藏如何设置它们 .

    Courtesy

  • 2

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

    另一方面, A builder pattern 本质上是一个包装器对象,它围绕您可能想要传递给构造函数调用的所有可能参数 . 这允许您使用setter方法慢慢构建参数列表 . 构建器类的另一个方法是build()方法,它只是将构建器对象传递给所需的构造函数,并返回结果 .

    在像Java这样的静态语言中,当您拥有多个(可能是可选的)参数时,这变得更加重要,因为它避免了为所有可能的参数组合设置伸缩构造器的要求 . 此外,构建器允许您使用setter方法来定义在调用构造函数后无法直接修改的只读或私有字段 .

    Basic Factory Example

    // 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");
    

    Basic Builder Example

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

  • 4

    Factory模式几乎可以看作是Builder模式的简化版本 .

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

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

    Builder 模式中,构造方法也会创建不同的子类型,但对象的组成可能在同一个子类中不同 .

    要继续汽车示例,您可能有一个 createCar 构建器方法,该方法创建一个带有4个柱面引擎的 Honda -typed对象,或者一个带有6个柱面的 Honda -typed对象 . 构建器模式允许更精细的粒度 .

    维基百科上提供了Builder patternFactory method pattern的图表 .

  • 0

    对于设计模式,通常没有“更有利”的解决方案适用于所有情况 . 这取决于您需要实施的内容 .

    来自维基百科:

    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

  • 0

    抽象工厂和构建器模式都是创建模式,但具有不同的意图 .

    Abstract Factory Pattern 强调相关对象族的对象创建,其中:

    • 每个族都是一组派生自公共基类/接口的类 .

    • 由于一次调用,每个对象立即返回 .

    Builder pattern 专注于逐步构建复杂对象 . 它将表示与构造复杂对象的过程分离,从而可以将相同的构造过程用于不同的表示 .

    • Builder对象封装了复杂对象的配置 .

    • Director对象知道使用Builder的协议,协议定义了构建复杂对象所需的所有逻辑步骤 .

  • 39
    • 逐步构造复杂对象:构建器模式

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

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

  • 1

    生成器和抽象工厂

    Builder设计模式在某种程度上与抽象工厂模式非常相似 . 这就是为什么能够在使用一种或另一种情况之间做出区别的重要性 . 对于抽象工厂,客户端使用工厂的方法来创建自己的对象 . 在Builder的情况下,Builder类被指示如何创建对象然后它被要求它,但是类的组合方式取决于Builder类,这个细节区分了两个模式 .

    产品的通用接口

    在实践中,由混凝土建造者创建的产品具有显着不同的结构,因此如果没有理由得到不同产品的共同父类 . 这也将Builder模式与Abstract Factory模式区分开来,后者创建从公共类型派生的对象 .

    来自:http://www.oodesign.com/builder-pattern.html

  • 249

    建造者和工厂之间的一个显着差异,我可以得出如下

    假设我们有车

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

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

    可能是那辆车以后不能很好地工作但是,你会有这个对象 .

    因为Factory Method会在单次调用中为您提供Car,而Builder会逐个构建 .

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

  • 50

    生成器模式和工厂模式,看起来都非常类似于肉眼,因为它们都为您创建对象 .

    但你需要仔细观察

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

    假设,你去了一家快餐店,你订购了 Food .

    1)什么食物?

    比萨

    2)什么浇头?

    辣椒,番茄,烧烤鸡,NO PINEAPPLE

    因此,不同种类的食物是由工厂模式制作的,但特定食物的不同变体(风味)是由Builder模式制作的 .

    不同种类的食物

    比萨饼,汉堡,意大利面

    比萨的变种

    只有奶酪,奶酪番茄辣椒,奶酪番茄等 .

    代码示例

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

  • -1

    复杂的结构是当要构造的对象由不同的其他对象组成时,这些对象由抽象表示 .

    考虑一下麦当劳的菜单 . 菜单包括饮料,主菜和鸡尾酒 . 取决于各个抽象的后代一起组成,创建的菜单具有另一种表示 .

    • 示例:可乐,巨无霸,炸薯条

    • 示例:雪碧,掘金,卷曲薯条

    在那里,我们得到了两个具有不同表示的菜单实例 . 反过来,施工过程仍然是一样的 . 您可以创建一个包含饮料,主菜和饮料的菜单 .

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

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

  • 0

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

    工厂模式指定您要创建一个共同族的对象,并希望它立即被cerated . 它用于更简单的对象 .

  • 1

    生成器和抽象工厂意味着不同的目的 . 根据正确的使用案例,您必须选择合适的设计模式 .

    生成器显着特征:

    • Builder模型使用简单对象并使用逐步方法构建复杂对象

    • Builder类逐步构建最终对象 . 此构建器独立于其他对象

    • 在这种情况下替换为工厂方法/抽象工厂:从客户端程序传递到可能容易出错的Factory类的参数太多

    • 某些参数可能是可选的,与Factory强制发送所有参数不同

    工厂(简易工厂)显着特点:

    • 创作模式

    • 基于继承

    • Factory返回Factory Method(接口),然后返回Concrete Object

    • 您可以用新的具体对象替换接口,而客户端(调用者)不应该知道所有具体实现

    • 客户端始终只访问接口,您可以在Factory方法中隐藏对象创建详细信息 .

    通常,设计开始使用工厂方法(更简单,更可定制,子类激增)并向Abstract Factory,Prototype或Builder发展(更灵活,更复杂)

    看看相关帖子:

    Keeping builder in separate class (fluent interface)

    Design Patterns: Factory vs Factory method vs Abstract Factory

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

    sourcemaking

    journaldev

  • -2

    一个例子

    1) using abstract factory:

    GUIFactory factory = new WindowsGUIFactory();
    Button button = factory.createButton(); // **creates a WindowsButton**
    

    2) using builder:

    GUIBuilder builder = new WindowsGUIBuilder();
    Button button = builder.createButton(); // **creates a Button.** 
    button.setOS = OSEnum.Windows;
    

    由于没有WindowsButton类,他(构建器)必须负责正确构建按钮,即: button.setOS = windows .

    它类似于在db设计中比较TPH与TPT .

  • 4

    抽象工厂类似于构建器,因为它也可以构造复杂的对象 . 主要区别在于Builder模式侧重于逐步构建复杂对象 . 抽象因子的重点是产品对象的系列(简单或复杂) .

  • 4

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

    有两种众所周知的方法来支配这种复杂性:

    • composition / aggregation:构造一个对象,构造它的dependend对象,然后连接togheter . 在这里,构建器可以使透明和灵活的过程确定引导组件构造的规则

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

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

  • 3

    构建模式强调创建对象的 complexity (由"steps"解决)

    抽象模式强调“只是”(多个但相关的)对象的“抽象” .

  • 370

    这是一种创建模式,因为它用于控制类实例化 . 构建器模式用于创建复杂对象,其中组成部分必须以相同顺序或使用特定算法创建 . 外部类(称为控制器)控制构造算法 .

    样品

    using System;
    
    using System.Collections.Generic;
    
    using System.Linq;
    
    using System.Text;
    
    namespace ConsoleApp_Design_Patterns
    {
    
        class BuilderDesignPattern
        {
            static void Main(string[] args)
            {
                //create a constructor object to start building
                Kid aKid = new Kid();
                aKid.Name = "Elizabeth";
    
                //Elizabeth use Monkey mold to make a monkey
                Console.WriteLine("{0} start making a monkey", aKid.Name);
                AnimalBuilder builderA = new MonkeyBuilder();
                aKid.MakeAnimal(builderA);
                builderA.aAnimal.ShowMe();
    
                //Elizabeth use Kitten mold to make a kitten
                Console.WriteLine("{0} start making a kitten", aKid.Name);
                AnimalBuilder builderB = new KittenBuilder();
                aKid.MakeAnimal(builderB);
                builderB.aAnimal.ShowMe();
    
                Console.Read();
            }
        }
        public abstract class AnimalBuilder
        {
            public Animal aAnimal;
    
            public abstract void BuildAnimalHeader();
            public abstract void BuildAnimalBody();
            public abstract void BuildAnimalLeg();
            public abstract void BuildAnimalArm();
            public abstract void BuildAnimalTail();
        }
        public class MonkeyBuilder : AnimalBuilder
        {
    
            public MonkeyBuilder()
            {
                aAnimal = new Monkey();
            }
    
            public override void BuildAnimalHeader()
            {
                aAnimal.Head = "Moneky's Head has been built";
            }
    
            public override void BuildAnimalBody()
            {
                aAnimal.Body = "Moneky's Body has been built";
            }
    
            public override void BuildAnimalLeg()
            {
                aAnimal.Leg = "Moneky's Leg has been built";
            }
    
            public override void BuildAnimalArm()
            {
                aAnimal.Arm = "Moneky's Arm has been built";
            }
    
            public override void BuildAnimalTail()
            {
                aAnimal.Tail = "Moneky's Tail has been built";
            }
        }
        public class KittenBuilder : AnimalBuilder
        {
            public KittenBuilder()
            {
                aAnimal = new Kitten();
            }
    
            public override void BuildAnimalHeader()
            {
                aAnimal.Head = "Kitten's Head has been built";
            }
    
            public override void BuildAnimalBody()
            {
                aAnimal.Body = "Kitten's Body has been built";
            }
    
            public override void BuildAnimalLeg()
            {
                aAnimal.Leg = "Kitten's Leg has been built";
            }
    
            public override void BuildAnimalArm()
            {
                aAnimal.Arm = "Kitten's Arm has been built";
            }
    
            public override void BuildAnimalTail()
            {
                aAnimal.Tail = "Kitten's Tail has been built";
            }
        }
        public abstract class Animal
        {
            public string Head { get; set; }
            public string Body { get; set; }
            public string Leg { get; set; }
            public string Arm { get; set; }
            public string Tail { get; set; }
    
    
            //helper method for demo the Polymorphism, so we can 
            //easily tell what type object it is from client.
            public abstract void Eat();
    
            //helper method for demo the result from client
            public void ShowMe()
            {
                Console.WriteLine(Head);
                Console.WriteLine(Body);
                Console.WriteLine(Leg);
                Console.WriteLine(Arm);
                Console.WriteLine(Tail);
                Eat();
    
            }
        }
        public class Monkey : Animal
        {
            //helper method to show monkey's property for demo purpose
            public override void Eat()
            {
                Console.WriteLine("Since I am Monkey, I like to eat banana");
            }
        }
        public class Kitten : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Since I am Kitten, I like to eat kitten food");
            }
        }
        public class Kid
        {
            public string Name { get; set; }
    
            //construct process to build an animal object, 
            //after this process completed, a object 
            //will be consider as a ready to use object.
            public void MakeAnimal(AnimalBuilder aAnimalBuilder)
            {
                aAnimalBuilder.BuildAnimalHeader();
                aAnimalBuilder.BuildAnimalBody();
                aAnimalBuilder.BuildAnimalLeg();
                aAnimalBuilder.BuildAnimalArm();
                aAnimalBuilder.BuildAnimalTail();
            }
    
    
        }
    }
    
  • 6

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

  • -2

    恕我直言

    Builder是某种更复杂的工厂 .

    in Builder you can instantiate objects with using another factories ,是构建最终有效对象所必需的 .

    所以,谈论复杂性的“创造模式”演变,你可以用这种方式思考它:

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

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

    这里构造器类充当主类和特定类型类之间的中介 . 更抽象 .

  • 2

    First some general things to follow my argumentation:

    设计大型软件系统的主要挑战是它们必须灵活且不易复杂 . 出于这个原因,有一些指标,如耦合和内聚 . 要实现易于更改或扩展其功能而无需从头开始重新设计整个系统的系统,您可以遵循设计原则(如SOLID等) . 过了一段时间,一些开发人员认识到,如果他们遵循这些原则,那么有一些类似的问这些标准解决方案被证明是设计模式 .

    因此,设计模式将支持您遵循一般设计原则,以实现具有高内聚力的松散耦合系统 .

    Answering the question:

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

    The Abstract Factory Pattern: GoF:“提供一个接口,用于创建相关或从属对象的族,而无需指定其具体类 . ”

    这意味着什么:通过提供这样的接口,对每个系列产品的构造函数的调用被封装在工厂类中 . 因为这是整个系统中唯一一个调用这些构造函数的地方,你可以通过实现一个新的工厂类来改变你的系统 . 如果您通过另一个交换工厂的代表,您可以交换一整套产品而无需接触大部分代码 .

    The Builder Pattern: GoF:“将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的表示 . ”

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

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

    在我看来,你不能说抽象工厂模式是Builder模式的大哥 . 是的,它们都是创作模式,但模式的主要意图完全不同 .

  • 245

    我相信,当您使用相同的代码库并更改需求时,可以在特定时间段内更轻松地理解/澄清Factory和Builder模式的使用和区别 .

    根据我的经验,通常,您从一个工厂模式开始,包括几个静态创建方法 . 由于您的对象层次结构变得更加复杂(或者当您添加更多类型时),您最终可能会使用更多参数填充方法,更不用说您将需要重新编译Factory模块 . 所有这些都会增加创建者方法的复杂性,降低可读性并使创建模块更加脆弱 .

    这一点可能是过渡点 . 从Factory转换为Builder模式 . 通过这样做,您可以在 construction parameters 周围创建一个包装器模块,然后您可以通过添加更多抽象(可能)和实现来表示新的(类似)对象,而无需触及实际的创建逻辑 . 所以你有更简单的逻辑和重新编译的源代码

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

  • 10

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

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

相关问题