Шаблон проектирования Service Locator и Dependeny Injection в Java

Cover Image for Шаблон проектирования 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 клиентский код указывает только свои зависимости и полагается на инфраструктуру для управления жизненным циклом и созданием сервисов. Это отделяет клиентский код от служб, упрощая его обслуживание и тестирование. Кроме того, это позволяет создать более гибкую и динамичную систему, поскольку сервисы можно легко заменять и заменять, не затрагивая клиентский код.

Возникли вопросы по статье, не работает код, хотелось бы больше информации - свяжитесь с нами и мы поможем