Вопрос новичка о внедрении зависимостей, когда метод должен создавать новые объекты - PullRequest
7 голосов
/ 11 июня 2009

Я читал о внедрении зависимостей и у меня есть простой вопрос. Я могу понять, как с помощью инжектора конструктора или сеттера необходимые зависимости автоматически связываются структурой DI. Что происходит, когда объект решает, что ему нужно создать новый объект из-за какого-то бизнес-процесса? Нужно ли мне всегда создавать Фабрику в таких ситуациях? Чтобы сделать этот вопрос менее абстрактным, вот пример.

Допустим, я пишу игру Asteriods. Посередине находится корабль, который может вращаться и стрелять в астероиды. Предположим, что корабль был создан, и оценили вещи, введенные. Когда вызывается playerShip.shoot(), нам нужно создать объект bullet. Объект маркера должен знать, в каком направлении он движется (direction) и с чего начать (point).

Обычно я бы сделал что-то вроде этого:

bullet = new Bullet( direction, point );

Однако это тесно связывает класс PlayerShip с классом Bullet. Как это должно работать при внедрении зависимости? Нужно ли создавать интерфейс BulletFactory и внедрять его реализацию в корабль?

Редактировать: На самом деле я не пишу астероиды. Это был простой пример, который, я думал, люди поймут. Я хотел что-то, что нужно было создать во время выполнения (а не при «подключении объектов»), у которого также были параметры для его конструктора.

Ответы [ 4 ]

3 голосов
/ 11 июня 2009

Зависит, если у вас будет только один тип пули ...

Если бы только один, я бы сказал, что с тобой все будет в порядке.

Но если у вас есть Bullet, DoubleBullet, PowerBullet, NukeBullet и т. Д.

Тогда я бы сделал базовый класс Bullet и все остальные Derrived из него

Тогда я бы сделал Bullet factory, и он бы имел CreateBullet, CreatePowerBullet и т. Д.

Другой вопрос, будет ли кто-нибудь еще делать пулю? Если так, то я бы создал фабрику, чтобы объединить логику создания в одном месте ...

В противном случае пахнет тем, что вы используете DI, просто чтобы использовать DI ...

2 голосов
/ 11 июня 2009

Вы в значительной степени получили это. Если вы хотите отделиться от класса Bullet, то, на мой взгляд, лучшее решение - внедрить фабрику, которая может создавать Bullet объекты.

Обратите внимание, что у вас есть несколько уровней косвенного обращения, каждый из которых дает вам больше гибкости, но требует больше кода и, возможно, более сложен для понимания. Самое простое - иметь оба типа BulletFactory и Bullet - конкретные типы. Это означает, что вы не можете легко иметь их различные реализации, но вы все равно можете расширить их оба и передать подкласс BulletFactory, который возвращает подклассы Bullet. Если ваша единственная цель для инъекций - облегчить юнит-тесты, я бы выбрал этот путь. Конечно, вы также можете сделать BulletFactory интерфейсом или Bullet интерфейсом, или и тем, и другим. Если вы собираетесь использовать разные орудия для целей, не связанных с тестированием, я бы выбрал этот путь.

Наконец, вы должны решить, стоят ли выгоды от отделения класса Bullet от вашего класса PlayerShip. Тесная связь не является злой, и ее не следует избегать любой ценой - она ​​имеет смысл в некоторых контекстах, а не в других. Только опыт поможет вам понять, когда нужно соединять классы, а когда их разделять.

1 голос
/ 11 июня 2009

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

public Type BulletType {get; set;}

public void fire()
{
    var b = (BulletType) kernel.get(BulletType);
    b.fire(point, direction);
}
1 голос
/ 11 июня 2009

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

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