Фабрика перечислений с использованием поставщика Java 8

#java #lambda #java-8 #factory #supplier

#java #лямбда #java-8 #фабрика #поставщик

Вопрос:

Я пытаюсь создать объекты (реализовать шаблон factory), используя Java 8 lambda и Supplier интерфейс.

 public static void main(final String[] args) {
    FactoryEnum.getEnumByClassName("CLASS_A").getSupplier().execute();
    FactoryEnum.getEnumByClassName("CLASS_B").getSupplier().execute();
  }
 

 enum FactoryEnum {

  CLASS_A(() -> A::new),

  CLASS_B(() -> B::new);

  private final Supplier<IConverter> supplier;

  FactoryEnum(final Supplier<IConverter> supplier) {
    this.supplier = supplier;
  }

  public static FactoryEnum getEnumByClassName(final String className) {
    return FactoryEnum.valueOf(className);
  }

  public IConverter getSupplier() {
    return supplier.get();
  }
}
 

 interface IConverter {

  void execute();
}
 

 class A implements IConverter {

  @Override
  public void execute() {

    System.out.println("Inside A"); //$NON-NLS-1$
  }

}
 

 class B implements IConverter {

  @Override
  public void execute() {
    System.out.println("Inside B");
  }

}
 

Когда я звонил FactoryEnum.getEnumByClassName("CLASS_A").getSupplier().execute() , я ожидал, что это вернет вновь созданный объект класса A, FactoryEnum.getEnumByClassName("CLASS_A").getSupplier().execute() а это вернет вновь созданный объект класса B. В то время как он возвращает мне лямбду. Почему он возвращает лямбда, а не объект IConverter . И как я могу это получить?

Комментарии:

1. Вопрос был закрыт до того, как я смог отправить свой ответ. Хотя это опечатка, я думаю, что объяснение того, почему это опечатка, может быть полезным. Вот оно pastebin.com/Q6bxCZhg

2. Кстати, нет смысла создавать дополнительный метод getEnumByClassName , который выполняет то же самое, что и уже существующий valueOf метод, особенно когда его единственная функция, отличное имя, вводит в заблуждение, поскольку аргумент не является именем класса.

3. @Michael: Спасибо за вашу помощь. Я написал это намеренно, потому что на самом деле я получил интерпретацию A::new для new A() , в то время как it is () -> {new A()} .

4. @Holger Да, это имеет смысл. Спасибо, что упомянули об этом.

Ответ №1:

 CLASS_A(() -> A::new)
 

означает

 CLASS_A(() -> { return A::new; })
 

что означает

 CLASS_A(() -> { return () -> { new A(); }; })
 

это не то, что вы пытались передать.

Попробуйте

 CLASS_A(A::new)
 

Комментарии:

1. или CLASS_A(() -> new A()) 🙂