Как и все в Guice, модульность, возможность многократного использования и удаление шаблонов являются основными понятиями всех утилит.
Конечно, все, что вы делаете в Guice, может быть имитировано на Java - ценой большого количества шаблонов. Итак ... реальный вопрос:
Как мы можем использовать TypeLiterals для написания более модульных / многократно используемых компонентов?
Сила TypeLiterals в Guice заключается в том, что он позволяет ссылаться на реализации службы, не определяя, что это за служба.
Давайте начнем с простого списка в программе, где у нас есть много типов списков, которые обрабатываются по-разному:
List<String> myStringList = new ArrayList<String>();
Теперь, как мне обработать эти строки? Во время выполнения нет способа «узнать», что это список строк. Так, часто я мог бы создать фабрику, которая получала бы обработку объектов для меня:
ProcessorFactory.get(String.class).process(myStringList);
Таким образом, я мог бы использовать фабрику (с кучей операторов if / else или case) для определения процессоров для разных типов данных. Мой конструктор для объекта, который использует эти процессоры и которому требуется доступ к различным реализациям процессоров, может выглядеть следующим образом:
public MyClass(Processor<String> strProcessor, Processor<Integer> intProcessor)P
{
//Simple enough, but alot of boiler plate is required to launch this constructor.
}
//and to invoke
new MyClass(PRocessorFactory.get(....), ProcessorFactory.get(...));
Пока все хорошо ... Пока мы не поймем, что есть лучший путь:
В мире Guice я могу забыть о написании этой фабрики - я могу явно связывать классы BIND с процессорами. Преимущество этого состоит в том, что нет никаких статических зависимостей - класс, который должен использовать реализации процессора, НЕ нуждается в статической зависимости от фабрики, классы вводятся напрямую. Таким образом, я могу легко определить класс, который использует сложные зависимости, без необходимости создания конструктора классов, ориентированного на фабрику ... Таким образом, у меня гораздо меньше шаблонов:
@Inject
public MyClass(Processor<String> implStr, Processor<Integer> implInt)
{
//Now , this method will work magically, because Guice is capable of
//Using the loaded modules, which define bindings between generics and their implementations
}
//Elsewhere I simply define a single guice module that does the binding, and make sure to load it before my application launches.
Существует хорошее руководство по реализации интерфейса и примерам привязки, здесь: http://thejavablog.wordpress.com/2008/11/17/how-to-inject-a-generic-interface-using-guice/