Это правильное использование внедрения зависимости - PullRequest
2 голосов
/ 04 июля 2011

Этот вопрос относится к одному из приведенных здесь: настраиваемые зависимости с легким макетом реализации по умолчанию .

Моя цель - спроектировать небольшую библиотеку по схеме DI. Имеет ли код, подобный следующему, правильное использование DI?

ValuesConfiguration - просто оболочка для карты. Это своего рода Value Object, он создается клиентом во время выполнения, поэтому нет возможности использовать внедрение зависимостей. Предыдущая версия (в связанном вопросе) имела эту конфигурацию в качестве аргумента конструктора, но, похоже, это не «реальная» зависимость.

public class Parser {

    private ValuesConfiguration configuration;
    private ValuesProvider valuesProvider;
    private ValuesMapper valuesMapper;

    public Parser() {}

    public Result parse(String parameterName) {
        initDefaults();           
        List<Values> values = valuesProvider.getValues(parameterName);
        ...
        return valuesMapper.transformValues(values, configuration);
    }

    private void initDefaults() {
        if(valuesProvider == null) {
            valuesProvider = DefaultsFactory.getDefaultValuesProvider();
        }
    }

    public void setConfiguration(ValuesConfiguration configuration) {
        this.valuesConfiguration = configuration;
    }

    public void setValuesProvider(ValuesProvider provider) {
        this.valuesProvider = provider;
    }

    ...

}

Не лучше ли добавить конфигурацию в качестве дополнительного параметра метода parse ()?

Ответы [ 4 ]

3 голосов
/ 04 июля 2011

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

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

Большой намек на то, что ваш конструктор не принимает значений, и вашим установщикам передаются общие объекты, которые не нужны после правильной инициализации компонента.

Как вы можете изменить его на использование DI.

public class Parser {

    private final ValuesProvider valuesProvider;
    private final ValuesMapper valuesMapper;
    private final ValuesConfiguration configuratrion;

    // all values injected.
    public Parser(ValuesProvider valuesProvider, ValuesMapper valuesMapper, ValuesConfiguration configuratrion) {
        this.valuesProvider = valuesProvider;
        this.valuesMapper = valuesMapper;
        this.configuratrion = configuratrion;
    }

    public Result parse(String parameterName) {
        List<Values> values = valuesProvider.getValues(parameterName);
        ...
        return valuesMapper.transformValues(values, configuration);
    }
 }
2 голосов
/ 04 июля 2011

Я бы не совмещал фабрики с DI. Это просто сбивает с толку. Например, здесь мы используем внедрение зависимости:

public void setValuesProvider(ValuesProvider provider) {
    this.valuesProvider = provider;
}

Но, подождите, здесь мы используем фабрику:

private void initDefaults() {
    if(valuesProvider == null) {
        valuesProvider = DefaultsFactory.getDefaultValuesProvider();
    }
}

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

setValuesProvider(myDefaultProvider)

Обратите внимание, что в этом случае вам придется тщательно задокументировать это. Или другим способом было бы просто использовать какое-то умное наследование (или, может быть, с помощью статики?), Чтобы иметь возможность вернуть ЛЮБОЙ ValuesProvider в состояние по умолчанию:

setValuesProvider(myProvider.defaultState())

Последнее имеет наибольшее значение для меня. Идея здесь заключается в том, что всякий раз, когда вы хотите поиграть с парсером, ValuesProvider ДОЛЖЕН быть предоставлен. Таким образом, я бы, скорее всего, использовал DI через конструктор Parser().

0 голосов
/ 24 июля 2011

Мне нравится следовать этому подходу со значениями по умолчанию:

public Parser(ValuesMapper valuesMapper, ValuesConfiguration configuratrion) {
    this(DefaultsFactory.getDefaultValuesProvider(), valuesMapper, configuratrion);
}

// all values injected.
public Parser(ValuesProvider valuesProvider, ValuesMapper valuesMapper, ValuesConfiguration configuratrion) {
    this.valuesProvider = valuesProvider;
    this.valuesMapper = valuesMapper;
    this.configuratrion = configuratrion;
}
0 голосов
/ 04 июля 2011

DI не всегда подходит.Использование фабрики DI не исключает вызова new во всех случаях.Ваш, кажется, один из тех.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...