2017-02-14 29 views
1

Я довольно новыми для Java и ниже мои картографа определения интерфейса:Factory Pattern, когда тип вывода отличается в Java

public interface CourseMapper { 
    Course map(JsonObject courseJson); 
    List<Course> map(JsonArray coursesJson); 
} 

public interface LocationMapper { 
    Location map(JsonObject locationJson); 
    List<Location> map(JsonArray locationsJson); 
} 

и ниже два класса:

public interface Location { 
    Long id(); 
    String name(); 
    Location mutate(Long id); 
} 

public interface Course { 
    Long id(); 
    String name(); 
    Course mutate(Long id); 
} 

Я необходимость основана на ключе (String), мне нужно вызвать соответствующую функцию map() соответствующего Mapper. Пример, если key=="location", мне нужно вызвать LocationMapper, и если key=="course", мне нужно вызвать CourseMapper (для gson Mapper) ...... и так далее.

Я попытался использовать шаблон Factory для этого же, но кажется, что то же самое не работает, когда Output имеет разный тип. Кто-нибудь знает, как добиться того же, без явного усложнения лестницы If-else.

+3

«а ниже - два класса» - это интерфейсы, а не классы. – alfasin

+0

, чтобы ваши экземпляры 'CourseMapper' и' LocationMapper' стали классами без гражданства? Я думаю, что окончательная стратегия зависит от этого фактора, так как вы не указали, хотите ли вы вызывать метод в тех же экземплярах или разных экземплярах для разных вызовов. Factory имеет смысл, когда вам нужны новые экземпляры для каждого вызова, и вы можете хранить эти экземпляры в карты, как указано в принятом ответе, если для каждого вызова не требуется создание нового экземпляра. –

+0

Мне нужно иметь новые экземпляры для каждого вызова, поэтому я изменяю принятый ответ, чтобы вписаться в шаблон Factory, в основном генерики - это то, что я искал. –

ответ

3

Самый простой подход должен иметь Map<String, Object> хранить картографами в:

private Map<String, Object> mappers; 

public <T> T getMapper(String key, Class<T> mapperType) { 
    Object mapper = mappers.get(key); 
    // code for when mapper == null 
    if (mapperType.isAssignableFrom(mapper)) { 
     return (T) mapper; 
    } else { 
     // code for when mapper is of wrong type 
    } 
} 

Как вы заметите, однако, это дает статические проверки типов, так что любое несоответствие типов будут найдены только при пробеге время.


Более сложный подход может сохранять (сортировать) проверки статического типа. Это в основном связывает тип результата с помощью ключа строки:

private static class MapperKey<T> { 
    private final String key; 

    public MapperKey(String key) { 
     this.key = key; 
    } 
} 

private Map<String, Object> mappers; 

public static final MapperKey<CourseMapper> COURSE_KEY = new MapperKey<CourseMapper>("course"); 

public <T> void addMapper(MapperKey<T> mapperKey, T mapper) { 
    mappers.put(mapperKey.key, mapper); 
} 

public <T> T getMapper(MapperKey<T> mapperKey) { 
    Object mapper = mappers.get(mapperKey.key); 
    // code for when mapper == null 
    return (T) mapper; 
} 

Этот подход, однако, зависит от пользователей, использующих предопределенные константы для MapperKey с, или создавать правильные ключи (правильный параметр типа для соответствующего ключа).


И, наконец, если вы можете заменить CourseMapper и LocationMapper интерфейсов с этим:

public interface Mapper<T> { 
    T map(JsonObject courseJson); 
    List<T> map(JsonArray coursesJson); 
} 

И если вам нужно только один картограф на один выход типа, вы можете использовать тип вывода в качестве ключа:

private Map<Class<?>, Mapper<?>> mappers; 

public <T> void addMapper(Class<T> outputType, Mapper<T> mapper) { 
    mappers.put(outputType, mapper); 
} 

@SuppressWarnings("unchecked") 
public <T> T getMapper(Class<T> outputType) { 
    return (T) mappers.get(outputType); 
} 
+0

Спасибо за подробный ответ - второе решение имеет прекрасный смысл! –

+0

С третьим вариантом, то есть с реализацией «Mapper », я думаю, он может решить свой первоначальный вызов, ** я попробовал использовать Factory Pattern для того же самого, но похоже, что то же самое не работает, когда Output имеет другой тип * *. –

 Смежные вопросы

  • Нет связанных вопросов^_^