构建器模式和构造函数的区别

Difference between builder pattern and constructor

构建器模式只是一种构建对象的方式,类似于构造函数的作用,那么为什么要使用构建器模式而不是普通的旧构造函数呢?

来自Wikipedia page

The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once

因此,如果我有一个需要很多构造参数的对象,并且这些参数需要以各种组合形式出现(因此使某些参数成为可选参数),那么构建器是一个很好的方法。

例如我可以为一个对象创建多个不同的构造函数,或者我可以执行以下操作:

new ObjectBuilder().withParam1(1).withParam4(4).withParam19(19).build();

从而允许我select所需的参数,而不必定义许多不同的构造函数。另请注意,上面的内容可以让您填充构建器,并多次设置 parameters/call build() 以轻松创建一组相关对象。

在构建器中构建对象 class 允许在一个地方封装与构建对象相关的逻辑。此外,与使用常规构造函数相比,您可以更轻松地处理对象构造所需的依赖关系。

换句话说 - 如果构建一个对象很复杂,并且依赖项很少 - 使用构建器模式,如果对象构建很简单(很少的逻辑和只有很少的参数) - 使用构造函数。

我同意您的观点,即 Builder 实际上只是一个美化的构造函数,而 "builder pattern is just a way to build an object similar to what a constructor does"。

但是,在以下几个场景中,构建 object 的复杂性使得 Builder 的使用引人注目。

Object 在一段时间内收集的依赖项

在 Java 中,StringBuilder 通常用于在一段时间内构建一个字符串,或者更确切地说,在一个复杂的过程中。例如,如果服务器通过套接字与客户端通信,并且想要将一些客户端响应附加到字符串,而不是其他响应,并且可能删除以前附加的某些响应,则 StringBuilder class 可以用来这样做。在client/serversession结束时,服务器可以调用StringBuilder#toString来获取构建的String.

很多参数

如果构造函数有几十个参数,使用构建器可能会使代码更具可读性或易于维护。

例如

new Foo(1,2,3,4,5,6,7,8,9,10,11,12)

Foo.newBuilder()
   .bar(1)
   .bar(2)
   .quux(3)
   ...
   .build()

构建object图

与"lots of parameters"场景类似,我认为构建器最引人注目的场景是在构建复杂的object图时。这个问题的其他答案是指伸缩anti-pattern。这种情况(构建一个复杂的 object 图)可能导致 "telescoping",Builder 有助于解决这个问题。

例如,假设您有一个 object-oriented 管道接口,其中 Pipeline 依赖于 Sequence,而 Sequence 又依赖于 StagePipelineBuilder 不仅会为 Pipeline 的构造函数提供一个很好的包装器,而且还会围绕 SequenceStage 的构造函数提供一个很好的包装器,允许您编写一个复杂的 Pipeline 来自单个 Builder 界面。

而不是像这样伸缩构造函数:

new Pipeline(
    new Sequence(
        new Stage(
            new StageFunction() {
                public function execute() {...}
            }
        ),
        new Stage(
            new StageFunction() {
                public function execute() {...}
            }
        )
    )
)

A PipelineBuilder 将允许您 "collapse" telescope。

Pipeline.newBuilder()
    .sequence()
        .stage(new StageFunction () {
            public function execute() {...}
        })
        .stage(new StageFunction () {
           public function execute() {...}
        })
    .build()

(尽管我以反映伸缩构造函数的方式使用缩进,但这只是装饰性的,而不是结构性的。)

constructor构造你需要的对象,而builder是helper object构造你需要的。我觉得太可怕了!

  1. 这与自然而然的、熟知的对象创建方法相矛盾。他们接下来会想出什么新办法?
  2. 您必须创建两个,而不是创建一个对象。
  3. 完全没有必要!我们总是必须为函数参数准备变量,而且我们从未使用过构建器。

例如:

// a class with ctor that takes lots of params
class Params
{
    Params(int,int,int,String,char,boolean,int){}
}

// We dont need a builder.
// A builder will do the same following thing.
int p1 = 20;
int p2 = 40 + 40;
int p3 = (67 >> 1) * 3;
String p4 = "go" + "to" + "church";
char p5 = ' ' == 32 ? '5' : '7';
boolean p6 = true;
int p7 = MATCH_PARAMS;
new Params(p1,p2,p3,p4,p5,p6,p7);

//There is also this design pattern
new Params(
    20,
    40 + 40,
    (67 >> 1) * 3,
    "go" + "to" + "church",
    ' ' == 32 ? '5' : '7',
    true,
    MATCH_PARAMS
   );

归根结底,如果您是建设者的粉丝,那没问题。但是当 Android 使构造函数被弃用时,我不喜欢那样。喜欢,类型类型;已弃用。