简体   繁体   中英

Understanding immutability with builder pattern and Cucumber-JVM and Guice

I'm using cucumber-jvm and cucumber-guice in my project for test automation. I have a POJO with builder pattern:

class Book {
  String title;
  String author;
  String date;
  // builder, getter, setter
}

Then, in cucumber test I need to share the state of the Book object among two steps:

class BookSteps {

  @Inject
  Book book;

  void firstStep() {
    buildBook();
  }

  void secondStep() {
    buildBook().setDate("2019-09-04");
  }

  Book buildBook() {
    return book = Book().BookBuilder().title("Foo").author("Bar").build();
  }

}

So, as I understood the builder pattern correctly, it creates an immutable object of book . But, why then I'm able to modify its state in secondStep() method by calling a setDate() on it and eventually modifying it?

You are able to modify state because builder pattern is not implemented correctly. In builder pattern:

  • You don't provide mutators(or setters) in your class. Only way to set properties of your class is via builder. Properties can be set only , either via builder constructor or via the mutator methods of builder. Usually for mandatory fields , you initialize them via builder constructor and then set other optional properties using builder setter methods.

So your Book class with builder patter should look like as below :

    public class Book {
    private String title;
    private String author;
    private String date;

    private Book(Builder builder) {
        title = builder.title;
        author = builder.author;
        date = builder.date;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getDate() {
        return date;
    }

    public static final class Builder {
        private String title;
        private String author;
        private String date;

        public Builder() {
        }

        public Builder title(String val) {
            title = val;
            return this;
        }

        public Builder author(String val) {
            author = val;
            return this;
        }

        public Builder date(String val) {
            date = val;
            return this;
        }

        public Book build() {
            return new Book(this);
        }
    }
}

And below is the test class:

 public class TestBookBuilder {
    public static void main(String[] args) {
        Book book = new Book.Builder().title("Book title").author("Book Author").date("25-01-2020").build();
    }
}

Now instance of Book class is immutable.

Hope it was helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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