Упражнение 26 Прагматического Программиста - PullRequest
4 голосов
/ 19 марта 2010

Фрагмент кода представлен в Прагматический программист на стр. 143 как:

public class Colada {
    private Blender myBlender;
    private Vector myStuff;

    public Colada() {
        myBlender = new Blender();
        myStuff = new Vector();
    }
    private doSomething() {
        myBlender.addIngredients(myStuff.elements());
    }
}

Это подчиняется Закону Деметры / Принципу Наименьшего Знания.

Является ли предпочтительным и есть ли какие-либо предостережения для замены его следующим, использующим инъекцию зависимости?

public class Colada throws IllegalArgumentException {
    private Blender myBlender;
    private Vector myStuff;

    public Colada(Blender blender, Vector stuff) {
        if (null == blender) {
            throw new IllegalArgumentException()
        } else {
            myBlender = blender;
        }
        if (null == stuff) {
            throw new IllegalArgumentException()
        } else {
           myStuff = stuff;
        }
    }

    public static Colada createDefaultInstance() {   
        Blender blender = new Blender();
        Vector stuff = new Vector();

        return new Colada(blender, stuff);
    }

    private doSomething() {
        myBlender.addIngredients(myStuff.elements());
    }
}

Ответы [ 2 ]

4 голосов
/ 19 марта 2010

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

Закон Деметры говорит что-то об API классов, а не о том, как они построены, поэтому я не вижу конфликта между Конструкторской инъекцией и Законом Деметры.

Тем не менее, как только вы решите использовать Dependency Injection, вы должны быть осторожны, чтобы избежать двусмысленности , когда дело доходит до создания объектов. Если вы продолжаете предлагать конструктор без параметров или метод статической фабрики, люди могут использовать его вместо того, чтобы позволить внешнему вызывающему объекту составить иерархию зависимостей.

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

2 голосов
/ 19 марта 2010

public getInstance (), не должно ли это быть "public static Colada getInstance ()"?

Оба хороши в моем мире, первый более читабельный, второй более динамичный. Но ни один из них не предполагает, что myBlender и myStuff являются свойствами, поэтому трудно понять, почему вы предпочли бы его динамический. Но если это то, что вы хотите, это выглядит хорошо. Вместо getInstance я бы просто создал два конструктора: один без аргументов, как в первом примере, а второй с двумя, как второй

Приветствия

Nik

...