简体   繁体   English

此代码模式的目的是什么?

[英]What purpose of this code pattern?

I am debugging somebody else's code and I just don't understand the benefit of coding this way in Java. 我正在调试其他人的代码,而我只是不明白在Java中以这种方式进行编码的好处。

I am not a Java Design Pattern expert but I would like to know when is this applicable? 我不是Java Design Pattern专家,但是我想知道何时适用?

public class MyClass {

    public static class Builder {
        //Getters and setters
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public MyClass(Builder builder) {
        //More Methods
    }

    public static void main(String[] args) {
        MyClass.Builder builder = MyClass.newBuilder();
        new MyClass(builder);
    }
}

This an implementation with few wrongs settings of builder pattern : 这是一个构建器模式的错误设置很少的实现:

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. Builder设计模式的目的是将复杂对象的构造与其表示分开。 By doing so the same construction process can create different representations. 这样,相同的构造过程可以创建不同的表示形式。

What is strange here is that the constructor of the Builder class is called from MyClass . 这里奇怪的是,从MyClass调用了Builder类的构造函数。 This is not generally done because ties the MyClass class to the Builder and not viceversa. 通常不会执行此操作,因为将MyClass类与Builder关联,反之亦然。

Additionally MyClass constructor should be private so that nobody can't access it directly, but only using the Builder . 另外, MyClass构造函数应该是private以便没有人不能直接访问它,而只能使用Builder

The right implementation should be as follow: 正确的实现方式如下:

public class MyClass {
    // Often fields are final to create an immutable class
    private final String fieldA;

    // Private constructor using Builder to set inner fields
    // To create MyClass you have to use Builder
    private MyClass(Builder builder) {
        // Setting fields from builder
        this.a = builder.getFieldA();
    }

    public static class Builder {
       // Fields on Builder are not final
       private String fieldA;

       //Getters and setters

       // Method to set field of builder
       public Builder setFieldA(String a) {
          this.a = a;
          return this;   // Returning this to chain setters
       }

    ...
        // Method to instantiate MyClass
        public MyClass build() {
           return new MyClass(this);
        }
    }
}

// Calling it as follow
MyClass a = new MyClass.Builder()
                .setFieldA("value")
                .setFieldB("value")
                .build();

According to the naming, this looks like one of the creational patterns - Builder pattern. 根据命名,这看起来像是一种创建模式-构建器模式。 However, this one is not well implemented. 但是,这一方法实施得不好。

The purpose of this pattern is to write readable and clean code to create a very complex object. 该模式的目的是编写可读且干净的代码来创建一个非常复杂的对象。 A good and yet simple example is StringBuilder . 一个很好而简单的例子是StringBuilder It is often implemented with a fluent interface - a typical example is Stream<T> . 它通常使用流畅的接口来实现-典型的示例是Stream<T>

The correct implementation is for example here . 正确的实现例如在这里 It allows you to create an object using methods returning the builder. 它允许您使用返回构建器的方法来创建对象。 Example: 例:

MyClass foo = MyClass.newBuilder()
    .cached()
    .with(new Feature1())
    .with(new Feature2())
    .foo()
    .bar()
    .build();

My personal point of view to this pattern: 我个人对这种模式的看法:

It encourages to create and use complex objects. 它鼓励创建和使用复杂的对象。 I prefer to refactor an object which has a builder with the smaller components. 我更喜欢重构一个对象,该对象的生成器具有较小的组件。 The object becomes easily testable and creatable through the constructors only. 仅通过构造函数,该对象就变得易于测试和创建。

The Builder pattern exposes what's called a Fluent API. 构建器模式公开了所谓的Fluent API。 Rather than individual set calls on each line, you can chain setters followed by a final build method to get the class instance. 可以在每个行上进行单独的set调用,而不是在每个行上进行单独的set调用,而可以使用final生成方法来链接该类实例。 There's not typically getters on a builder object. 通常,在构建器对象上没有吸气剂。

That constructor is a form of a copy constructor. 该构造函数是副本构造函数的一种形式。 I'm guessing there's other code using it to build unique instances of an object with the same data. 我猜想还有其他代码使用它来构建具有相同数据的对象的唯一实例。

The last line of your main method isn't doing anything since you're not assigning that new class. main方法的最后一行不执行任何操作,因为您没有分配该新类。 In any case, as mentioned, you'd typically use a build method, not pass the builder into a constructor 如前所述,无论如何,您通常会使用构建方法,而不是将构建器传递给构造器

MyClass foo = MyClass.newBuilder()
    .withBar("blah")
    .build();

MyClass.newBuilder() could also be replace by new MyClass.Builder() MyClass.newBuilder()也可以替换为new MyClass.Builder()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM