Эффективная Java от Джошуа Блоха: Item1 - Static Factory Method

Я читаю Effective Java Джошуа Блоха, и у меня есть вопрос по Item1 Static Factory Method.

Цитата [Блох, стр.7]

Интерфейсы не могут иметь статических методов, поэтому по соглашению статические фабричные методы для интерфейса с именем Type помещаются в класс, не поддерживающий создание экземпляров, с именем Types. Например, Java Collections Framework предоставляет неизменяемые коллекции, синхронизированные коллекции и тому подобное. Почти все эти реализации экспортируются с помощью статических фабричных методов в одном неинстанцируемом классе (java.util.Collections). Все классы возвращаемых объектов не являются общедоступными.

В порядке. Когда я смотрю исходный код, я вижу java.util.Collection интерфейс и java.util.Collections класс с частным конструктором (класс, не требующий создания экземпляров). и я вижу, что класс Collections, не являющийся экземпляром, имеет все статические методы, как и сказал Блох. Но я не вижу связи между двумя классами, как сказал Блох.

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

  1. Может ли кто-нибудь указать мне на очевидное?

  2. что это значит, когда он сказал

Все классы возвращаемых объектов не являются общедоступными

Вот где я получаю исходные коды java: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collection.java?av=f


person Thang Pham    schedule 25.05.2011    source источник
comment
См. Также Блох, элемент 1.   -  person trashgod    schedule 26.05.2011
comment
все, что касается Блоха, по умолчанию для меня плюс один.   -  person Thufir    schedule 01.09.2013


Ответы (5)


  1. Интерфейсы не могут иметь статических методов, поэтому по соглашению статические фабричные методы для интерфейса с именем Type помещаются в класс, не являющийся экземпляром, с именем Types.

    Дело просто в множественном числе в поле «Тип [ы]». Итак, если ваш интерфейс называется Foo, и вы хотите создать некоторую реализацию с именем MyFoo, тогда ваша фабрика с методами для создания экземпляров должна вызываться Foos по соглашению.

  2. Все классы возвращаемых объектов не являются общедоступными

    Это означает, что классы объектов, возвращаемых из фабричных методов, имеют частный модификатор видимости или модификатор видимости по умолчанию, как в private class MyFoo{}, так что они не могут быть созданы никакими другими средствами, кроме их фабричных методов. Поскольку вы не можете построить объект, используя оператор new из частного внутреннего или частного класса пакета вне их области (отражение в стороне).

e.g.:

 public interface Foo{ //interface without plural 's' (question 1)
     public void bar();
 }
 public abstract class Foos(){ // abstract factory with plural 's' (question 1)
    public static Foo createFoo(){
        return new MyFoo();
    }
    private class MyFoo implements Foo{ // a non visible implementation (question 2)
       public void bar(){}
    }
 }
person fasseg    schedule 25.05.2011
comment
Отличное объяснение по 1. Я так понимаю, должно быть лучше. Большое Вам спасибо. Для 2: в чем преимущество того, что возвращаемый объект является экземпляром частного класса? - person Thang Pham; 25.05.2011
comment
вы можете переключать реализации без ведома пользователя API, поскольку он никогда не создавал ни один из объектов сам, используя new. Поэтому, если вам нужно что-то переопределить, вы можете создать новую версию без каких-либо изменений API. - person fasseg; 25.05.2011
comment
Хм, я обнаружил, что мне нужно добавить модификатор static к внутреннему классу MyFoo, чтобы заставить его скомпилировать ... В противном случае я получаю сообщение об ошибке, что не существует включающего экземпляра Foos. Я делаю что-то неправильно? - person Mats_SX; 20.01.2014
comment
@Mats_SX: Я только что кое-что прочитал по этому поводу. javarevisited.blogspot.sg/2012/02/ В основном это сводится к тому, что во внутреннем классе MyFoo вы создаете экземпляр Foos и ссылаетесь на него. - person MacD; 09.02.2014
comment
Хорошим примером является Lists. из Guava, который содержит статические фабричные функции для List экземпляров. Например, вы можете создать список строк со следующим кодом: List<String> list = Lists.newArrayList("first", "second", "third") - person pedromanoel; 13.03.2017

Допустим, у вас есть интерфейс с именем List, и вы хотите использовать статический фабричный метод для создания различных типов списков. Вы не можете определить статические фабричные методы в List интерфейсе, потому что это интерфейс. Итак, что вам нужно сделать, это иметь класс, возвращающий экземпляры классов, реализующих List

public class ListFactory{
  private ListFactory(){}
  public static List makeArrayList(){...}
  public static List makeLinkedList(){...}
  public static List makeCrazyList(){...}
}

Ты не сможешь это сделать

public interface List{
   public static List makeArrayList();
   public static List makeLinkedList();
   public static List makeCrazyList();
}

Поскольку List - это интерфейс.

person Alvin    schedule 25.05.2011
comment
Начиная с java 8, было снято ограничение, что интерфейсы не могут содержать статический метод. - person Mohdroid; 26.04.2021

Возьмем, например, Collections.unmodifiableList (...). Он возвращает некоторую реализацию List. Но имя класса реализации значения не имеет. Кроме того, указанный класс только создается с помощью статического фабричного метода.

person Dilum Ranatunga    schedule 25.05.2011

1) Я не понимаю вашего вопроса. Collection - это интерфейс, а Collections имеет некоторые заводские методы, такие как emptyList

2) Например, экземпляр List, возвращаемый Collection.emptyList, является экземпляром частного класса, реализующего интерфейс List.

person Kaj    schedule 25.05.2011
comment
У меня к вам еще один вопрос. Для 2 в чем преимущество того, что возвращаемый объект является экземпляром частного класса? - person Thang Pham; 25.05.2011

Это просто означает, что типом возвращаемого значения статических фабричных методов в Collections (и других подобных ему классов) являются типы интерфейсов (например, List), а не конкретные классы реализации (например, java.util.Collections.UnmodifiableList), которые не видны пользователям, поскольку это только усложняет ситуацию. и увеличить размер API.

person ColinD    schedule 25.05.2011