Образец Джошуа Блоха и предупреждения PMD - PullRequest
5 голосов
/ 30 мая 2011

Я написал класс, используя шаблон Builder Джошуа Блоха, который похож на этот пример Pizza:

public class Pizza {
  private int size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder {
    //required
    private final int size;

    //optional
    private boolean cheese = false;
    private boolean pepperoni = false;
    private boolean bacon = false;

    public Builder(int size) {
      this.size = size;
    }

    public Builder cheese(boolean value) {
      cheese = value;
      return this;
    }

    public Builder pepperoni(boolean value) {
      pepperoni = value;
      return this;
    }

    public Builder bacon(boolean value) {
      bacon = value;
      return this;
    }

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

  private Pizza(Builder builder) {
    size = builder.size;
    cheese = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon = builder.bacon;
  }
}

, но PMD сообщил о 2 предупреждениях:

  1. (Указывает на методBuilder.build ()) Избегайте создания экземпляров через частные конструкторы извне класса конструктора.Использование частных конструкторов вне класса конструктора часто вызывает генерацию метода доступа.Фабричный метод или неприватизация конструктора может устранить эту ситуацию.Сгенерированный файл класса на самом деле является интерфейсом.Это дает доступному классу возможность вызывать новый скрытый конструктор области действия пакета, который принимает интерфейс в качестве дополнительного параметра.Это эффективно превращает частный конструктор в конструктор с областью действия пакета, и его трудно различить.
  2. Класс не может быть создан и не предоставляет никаких статических методов или полей.Класс, который имеет частные конструкторы и не имеет никаких статических методов или полей, не может быть использован.

Стоит ли просто игнорировать эти предупреждения?

Другой вопрос: закрытые поля в классе Pizza и Builder являются дубликатами.Это будет раздражать, когда количество приватных полей станет больше.Есть ли способ избежать этого?

Ответы [ 2 ]

2 голосов
/ 30 мая 2011

О том, как удалить дубликаты.

Я получу больше отрицательных голосов :) Но может быть что-то подобное?

class Pizza {
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;

public static class Builder {
    private Pizza pizza = new Pizza();

    public Builder(int size) {
        pizza.size = size;
    }

    public Builder cheese(boolean value) {
        pizza.cheese = value;
        return this;
    }

    public Builder pepperoni(boolean value) {
        pizza.pepperoni = value;
        return this;
    }

    public Builder bacon(boolean value) {
        pizza.bacon = value;
        return this;
    }

    public Pizza build() {
        return pizza;
    }
}

private Pizza() {
}
}
1 голос
/ 30 мая 2011

приватные поля в классе Пицца и Строитель дублируется. Это будет раздражает, когда число частных поля становятся больше. Есть ли способ избежать этого?

Лично я могу обойти это, используя третий класс объектов со статическими значениями, который содержит все поля, и использую его как в конструкторе, так и в основном классе (доступ к полям обрабатывается делегированием). Конечно, это может привести к увеличению числа строк / классов, но это неоценимо в случае, если ваши сборщики столкнутся с большим количеством полей и проверок.

Кроме того, не мешало бы фактически предоставить статический метод для класса Pizza, который создает объект Pizza с обязательными полями. Если, конечно, вы не уверены, что такое обязательные поля, или боитесь, что обязательные поля могут измениться в ходе эволюции вашего класса. Суть в том, что до тех пор, пока вы можете оправдывать свои действия после долгих раздумий (как говорит Джошуа Блох), вы можете спокойно игнорировать эти предупреждения, зная, что вы знаете, что делаете. : -)

Одноразовый фрагмент:

public class Pizza {

    private final PizzaVO vo;

    private static class PizzaVO {

        int size;

        boolean cheese;

        boolean pepperoni;

        boolean bacon;
    }

    public static class Builder {

        private final PizzaVO vo = new PizzaVO();

        public Builder(int size) {
            vo.size = size;
        }

        public Builder cheese(boolean value) {
            vo.cheese = value;
            return this;
        }

        public Builder pepperoni(boolean value) {
            vo.pepperoni = value;
            return this;
        }

        public Builder bacon(boolean value) {
            vo.bacon = value;
            return this;
        }

        public Pizza build() {
            return new Pizza(vo);
        }
    }

    private Pizza(PizzaVO vo) {
        this.vo = vo;
    }

    public int getSize() {
        return vo.size;
    }

    // other getter setter methods as per your taste

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...