Chuyển đến nội dung chính

Effective Java 02 - Consider a builder when faced with many constructor parameters

 Khi một Object có thể được tạo từ nhiều attributes khác nhau thì chúng ta nên consider sử dụng Builder Pattern thay cho Static factories hoặc Constructors.

Ví dụ sử dụng Builder Pattern:

// Builder Pattern
public class NutritionFacts {
  private final int servingSize;
  private final int servings;
  private final int calories;
  private final int fat;
  private final int sodium;
  private final int carbohydrate;
  public static class Builder {
  // Required parameters
  private final int servingSize;
  private final int servings;
  // Optional parameters - initialized to default values
  private int calories = 0;
  private int fat = 0;
  private int sodium = 0;
  private int carbohydrate = 0;
  public Builder(int servingSize, int servings) {
    this.servingSize = servingSize;
    this.servings = servings;
  }
  public Builder calories(int val) {
    calories = val;
    return this; 
  }
  public Builder fat(int val) {
    fat = val;
    return this; 
  }
  public Builder sodium(int val) { 
    sodium = val;
    return this; 
  }
  public Builder carbohydrate(int val) {
    carbohydrate = val;
    return this;
  }
  public NutritionFacts build() {
    return new NutritionFacts(this);
  }
}
  private NutritionFacts(Builder builder) {
    servingSize = builder.servingSize;
    servings = builder.servings;
    calories = builder.calories;
    fat = builder.fat;
    sodium = builder.sodium;
    carbohydrate = builder.carbohydrate;
  }
}

Client tạo instance:

NutritionFacts cocaCola = new NutritionFacts
  .Builder(240, 8)
  .calories(100)
  .sodium(35)
  .carbohydrate(27).build();

Ưu điểm

  • Code ở client dễ đọc.
  • Có thể validate các parameters trước khi tạo instance bằng cách implement trong method build.
  • Kỹ thuật kế thừa Abstract class với Builder

    // Builder pattern for class hierarchies
    public abstract class Pizza {
      public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
      final Set<Topping> toppings;
      abstract static class Builder<T extends Builder<T>> {
        EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
        public T addTopping(Topping topping) {
          toppings.add(Objects.requireNonNull(topping));
          return self();
        }
        abstract Pizza build();
        // Subclasses must override this method to return "this"
        protected abstract T self();
        }
      }
      Pizza(Builder<?> builder) {
        toppings = builder.toppings.clone();
      }
    }
    

  • Mỗi parameter tương ứng với một method builder và Object được tạo khi invoke method build làm cho Builder Pattern flexible hơn so với các cách tạo Object khác.

Nhược điểm

  • Chỉ hiệu quả đối với trường hợp class có nhiều optional attributes và việc sử dụng static factories hay constructor gây khó khăn cho client. Do vậy không nên quá lạm dụng Builder Pattern.
  • Việc sử dụng Builder Pattern có thể gây ảnh hưởng performance vì mỗi lần tạo object sẽ phải tạo builder cho nó.

Tổng kết

In summary, the Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if many of the parameters are optional or of identical type. Client code is much easier to read and write with builders than with telescoping constructors, and builders are much safer than JavaBeans.

Hy vọng bạn có được thêm kiến thức mới.
Keep learning 💪

Nhận xét

Bài đăng phổ biến từ blog này

Effective Java 01 - Consider static factory methods instead of constructors

Ở bài viết này, chúng ta sẽ bàn về cách để tạo Object trong Java. Để tạo mới một Object trong Java thì cách truyền thống là provide một public constructor và sử dụng keyword new ở client. Có một cách khác mà chúng ta nên biết và consider để sử dụng thay cho cách truyền thống đó là provide static factory methods . Vậy ưu điểm và nhược điểm của static factory methods là gì, chúng ta sẽ cùng tìm hiểu trong bài viết này. Cách truyền thống: Provide a public constructor Ví dụ: Class Student.java public class Student { private long id ; private String name ; public Student ( long id , String name ) { this . id = id ; this . name = name ; } } Client có thể tạo instance bằng cách sử dụng new keyword: Student student = new Student ( 1 , "Nguyễn Văn A" ); Sử dụng Static Factory Methods Ví dụ: Class Student.java public class Student { private long id ; private String name ; private Student ( long id , Strin...