2015-08-10 11 views
0

У меня есть следующие перечисления:Есть ли что-то не так с локальным классом определяется с п тела конструктора

enum FilterFactory { 

    INSTANCE; 

    private final Map<FilterType, Creator> creators; 

    private FilterFactory() { 
     creators = new HashMap<>(); 

     class SimplCreator implements FilterCreator{ 
      @Override 
      public FilterDTO createDto() { 
       return new FilterDTO(); 
      } 
     } //Local class within the constructor 

     creators.put(FilterType.DATE, new FilterCreator(){ 
      @Override 
      public FilterDTO createDto() { 
       return new DynamicDTO(); 
      } 
     }); 

     creators.put(FilterType.DROP_DOWN_LIST, new SimplCreator()); 
     creators.put(FilterType.FIELD, new SimplCreator()); 
    } 

    private static interface Creator{ 
     public FilterDTO createDto(); 
    } 
    //Other staff 
} 

Дело в том, я никогда не использовал местные классы в застройщиках органов. Может ли это вызвать некоторые ошибки, неужели это плохо? Кроме того, конструктор конструктора enu.

+3

Нет ничего плохого в этом. На самом деле, это, вероятно, хорошая практика, так как нет необходимости усложнять код для других разработчиков, предоставляя SimplCreator вне метода, который его использует. (Кстати, если FilterType является перечислением, вы, вероятно, должны использовать [EnumMap] (http://docs.oracle.com/javase/8/docs/api/java/util/EnumMap.html), а не HashMap.) – VGR

+0

@ VGR Exccellent poitn. Действительно, я должен. Спасибо. –

+0

Кроме того, если вы используете Java 8, это звучит как работа для lambdas :) – yshavit

ответ

1

Ваш подход прекрасно, но в Java 8 вы можете сделать это немного лучше, используя ссылки метод или лямбды (и замене Творца с более стандартным Supplier<FilterDTO>):

import java.util.function.Supplier; 

enum FilterFactory { 

    INSTANCE; 

    private final Map<FilterType, Supplier<FilterDTO>> creators; 

    private FilterFactory() { 
     creators = new EnumMap<>(FilterType.class); // a bit more efficient :) 
     creators.put(FilterType.DATE, DynamicDTO::new); 
     creators.put(FilterType.DROP_DOWN_LIST, SimpleDTO::new); 
     creators.put(FilterType.FIELD, SimpleDTO::new); 
    } 

    // other stuff ... 
} 

Здесь я использовал застройщика, method reference для конкретизации Supplier<FilterDTO>. Я мог бы так же хорошо использовать лямбда-выражения, который не говорит «дал ничего, дайте мне FilterDTO»:

creators.put(FilterType.DATE,() -> new DynamicDTO()); 
... 

два варианта (метод ссылки против lamdbas) в основном эквивалентны, и вы должны использовать в зависимости от того понятнее вы (Java's language architect himself). Я лично нахожу метод эталонным визуально более ясным, хотя он немного привыкает.

1

Единственная проблема, которую я вижу, заключается в том, что вы создаете новые экземпляры FilterCreator для каждого экземпляра FilterFactory (который занимает больше памяти). Вы можете предотвратить это путем создания некоторых констант:

enum FilterFactory { 

    INSTANCE; 

    private final Map<FilterType, Creator> creators = new HashMap<>(); 

    private static final SimplCreator DEFAULT_CREATOR = new Creator() { 
     @Override 
     public FilterDTO createDto() { 
      return new FilterDTO(); 
     } 
    } 

    private static final FilterCreator DYNAMIC_CREATOR = new Creator(){ 
     @Override 
     public FilterDTO createDto() { 
      return new DynamicDTO(); 
     } 
    } 

    private FilterFactory() { 
     creators.put(FilterType.DATE, DYNAMIC_CREATOR); 
     creators.put(FilterType.DROP_DOWN_LIST, DEFAULT_CREATOR); 
     creators.put(FilterType.FIELD, DEFAULT_CREATOR); 
    } 

    private static interface Creator{ 
     FilterDTO createDto(); 
    } 
    //Other stuff 
} 
+0

Смотрите, я бы не хотел выставлять объект DEFAULT_CREATOR за пределами конструктора .... –

+0

Я полагаю, что вы имели в виду '= new Creator() {'? –

+0

«для каждого экземпляра FilterFactory» - все экземпляры? FilterFactory - однополюсный одноэлементный. :) – yshavit