Шаблон проектирования Service Locator и Dependeny Injection в Java
- Шаблон Service Locator'
- Внедрение зависимостей
- Пример реализации
- Выводы
Содержание
Service Locator
Для начала вспомним что такое
Service Locator
Service Locator — это шаблон проектирования в Java, который используется для управления зависимостями между компонентами в программной системе. Это способ централизованного доступа к службам, упрощающий управление и обновление зависимостей системы. и что такое
Внедрение зависимостей
Внедрение зависимостей (DI) — это шаблон проектирования, который используется в объектно-ориентированном программировании для управления зависимостями между компонентами в программной системе. Это способ отделить реализацию компонента от его зависимостей, делая код более гибким, удобным в сопровождении и тестируемым.
Расмотрим код, который поможет нам определить чем эти 2 подхода отличаются:
interface TextEditor {
void setTextProcessor(TextProcessor processor);
String processText(String text);
}
class SimpleTextEditor implements TextEditor {
private TextProcessor processor;
@Override
public void setTextProcessor(TextProcessor processor) {
this.processor = processor;
}
@Override
public String processText(String text) {
return processor.process(text);
}
}
interface TextProcessor {
String process(String input);
}
class LowerCaseProcessor implements TextProcessor {
@Override
public String process(String input) {
return input.toLowerCase();
}
}
class UpperCaseProcessor implements TextProcessor {
@Override
public String process(String input) {
return input.toUpperCase();
}
}
// Service Locator
class ServiceLocator {
private static Map<String, TextProcessor> processors = new HashMap<>();
static {
processors.put("lower", new LowerCaseProcessor());
processors.put("upper", new UpperCaseProcessor());
}
public static TextProcessor getService(String type) {
return processors.get(type);
}
}
// Dependency Injection
class Main {
public static void main(String[] args) {
// Service Locator
SimpleTextEditor serviceLocatorEditor = new SimpleTextEditor();
serviceLocatorEditor.setTextProcessor(ServiceLocator.getService("lower"));
System.out.println(serviceLocatorEditor.processText("HELLO"));
serviceLocatorEditor.setTextProcessor(ServiceLocator.getService("upper"));
System.out.println(serviceLocatorEditor.processText("hello"));
// Dependency Injection
SimpleTextEditor diEditor = new SimpleTextEditor();
diEditor.setTextProcessor(new LowerCaseProcessor());
System.out.println(diEditor.processText("HELLO"));
diEditor.setTextProcessor(new UpperCaseProcessor());
System.out.println(diEditor.processText("hello"));
}
}
В шаблоне Service Locator ServiceLocator
класс действует как централизованный репозиторий для всех доступных текстовых процессоров. Класс SimpleTextEditor
использует ServiceLocator
для получения желаемого текстового процессора, а не создает его экземпляр напрямую.
В примере с внедрением зависимостей (Dependeny Injection DI) SimpleTextEditor
класс получает текстовый процессор через свой setTextProcessor
метод. Класс Main
отвечает за создание экземпляров текстовых процессоров и внедрение их в SimpleTextEditor
.
В шаблоне Service Locator код клиента отвечает за поиск нужной службы и доступ к ней. Это может привести к тесной связи между клиентским кодом и службами, что усложнит поддержку и тестирование кода. С другой стороны, при внедрении зависимостей клиентский код просто указывает свои зависимости и полагается на то, что вызывающая сторона предоставит их, что приводит к слабой связи между клиентским кодом и службами. Это упрощает поддержку и тестирование кода, поскольку сервисы можно легко заменить.
В шаблоне Service Locator ответственность за управление жизненным циклом и созданием сервисов лежит на клиентском коде. Это может привести к тесной связи между клиентским кодом и службами, что усложнит поддержку и тестирование кода.
С другой стороны, с IoC и DI клиентский код указывает только свои зависимости и полагается на инфраструктуру для управления жизненным циклом и созданием сервисов. Это отделяет клиентский код от служб, упрощая его обслуживание и тестирование. Кроме того, это позволяет создать более гибкую и динамичную систему, поскольку сервисы можно легко заменять и заменять, не затрагивая клиентский код.