Статический фабричный метод не работает

Начал читать "Эффективная Java" и не могу понять, почему у меня не работает, когда я пытаюсь написать пример..

Ошибка компиляции:

Ошибка: (12, 16) java: конструктор Car в классе Car не может быть применен к заданным типам;


public class Car {

    String model;

    //no private constructor

    public static Car fromModel(String model) {
        return new Car(model);
    }

}

Здесь все в порядке:

public class Car {

    String model;

    //no private constructor

    public static Car fromModel(String model) {
        return new Car(model);
    }
}

//Here everything is OK:

public class Car {

    String model;

    private Car(String model) {
        this.model = model;
    }

    public static Car fromModel(String model) {
        return new Car(model);
    }

}

Почему я должен генерировать конструктор, если «Учитывайте статические фабричные методы вместо конструкторов» ???


person Dmytro Manzhula    schedule 12.05.2018    source источник
comment
Почему вы ожидаете первую работу? Вы вызываете несуществующий конструктор.   -  person DontKnowMuchBut Getting Better    schedule 12.05.2018


Ответы (3)


«Используйте статические фабричные методы вместо конструкторов» относится к предоставлению доступа к созданию экземпляров ваших объектов пользователям вашей библиотеки за пределами вашего класса.

Конструктор, который использует ваш фабричный метод, является деталью реализации вашего фабричного метода так же, как метод static public — метод и частный конструктор вместе составляют один фабричный метод для внешних пользователей вашей библиотеки классов.

person Sergey Kalinichenko    schedule 12.05.2018
comment
Если я правильно понимаю, у меня должен быть один частный конструктор со всеми переменными, а затем может быть несколько частных статических методов? - person Dmytro Manzhula; 12.05.2018
comment
@mnjl Хотя это очень распространенный способ реализации шаблона, особенности зависят от вас. Вы можете определить несколько частных конструкторов, если вам это удобнее. - person Sergey Kalinichenko; 12.05.2018

Ваш пример может быть очень простым. Обычный конструктор может иметь большое количество параметров. В таких случаях вы можете «назвать» каждый конструктор, создав метод статического конструктора. Во-вторых, используя этот шаблон, вы можете скрыть часть параметров конструктора.

Пример:

class FinishEvent {
   privare Car response;
   private boolean success;
   private String errorMessage;

  //private constructor, we delegate creating to named methods
   private FinishEvent(Car response, boolean success, String errorMessage) {... } 

}

Как вы можете видеть, здесь ответом является Car, но когда событие прошло успешно, нам не нужно заполнять errorMessage. С другой стороны, если процесс не удался, у нас нет ответа для заполнения.

Здесь пригодятся статические методы конструктора:

public static FinishEvent success(Car response){
  return new Car(response, true, null);
}
public static FinishEvent failed(String errorMessage){
  return new Car(null, false, errorMessage);
}

Имея этот API другие пользователи вашего класса, умейте им пользоваться.

Если бы ваш Car был абстрактным методом, то ваши фабричные методы могли бы обеспечить реализацию. Таким образом, вы можете скрыть все реализации от пользователя, но предоставить способ их создания.

person Beri    schedule 12.05.2018
comment
предположим, я понял. Пожалуйста, проверьте мой ответ ниже, он выглядит правильно для меня в соответствии с вашим объяснением ... Спасибо! - person Dmytro Manzhula; 12.05.2018
comment
@mnjl правда, ваш ответ правильный, но вставка кода без объяснения не считается ответом. Это может быть копипаст или очередной плагиат. Пожалуйста, добавьте несколько комментариев :) - person Beri; 12.05.2018
comment
Готово, пожалуйста, дайте отзыв, если вам все еще не хватает разъяснений. - person Dmytro Manzhula; 12.05.2018

Ответ для меня заключается в том, что мне нужен хотя бы один частный конструктор для создания нескольких статических методов.

Нет ошибок компиляции:

public class Car {

String model;
String color;
String modelYear;

private Car(String model, String color, String modelYear) {
    this.model = model;
    this.color = color;
    this.modelYear = modelYear;
}

public static Car fromModelAndColor(String model, String color){
    return new Car(model, color, null);
}

public static Car fromModelAndYear(String model, String modelYear){
    return new Car(model, null, modelYear);
}

public static Car fromModelAndColorAndYear(String model, String color, String modelYear){
    return new Car(model, color, modelYear);
}

}

person Dmytro Manzhula    schedule 12.05.2018
comment
Раньше я предполагал, что мне не нужен никакой конструктор, потому что: вместо конструкторов используйте статические фабричные методы. Теперь вижу, что меня ввели в заблуждение... И обсуждение выше многое прояснило мой вопрос. Я только что отредактировал свой ответ. - person Dmytro Manzhula; 12.05.2018