MVC, DI (внедрение зависимости) и создающий Образцовый экземпляр из Контроллера

Мой Диспетчер "выбирает" корректный Контроллер; затем создавая экземпляр Контроллера (DependencyInjectionContainer передается конструктору Controller); затем называя метод некоторого Контроллера...

class UserController extends Controller
{

  public function __construct(DependencyInjectionContainer $injection) {
    $this->container = $injection;
  }

  public function detailsAction() {
    ...
  }

}

DependencyInjectionContainer содержит объект адаптера DB, Объект конфигурации и т.д. Теперь давайте посмотрим, какой detailsAction () метод содержит...

public function detailsAction() {

  $model = new UserModel();
  $model->getDetails(12345);

}

Поскольку Вы видите, что я создаю новый экземпляр UserModel и называю getDetails методы. getDetails модели () метод должен соединиться с дб для получения информации о пользователе. Для соединения с DB, UserModel должен смочь получить доступ к адаптеру DB.

Что правильный путь состоит в том, чтобы передать DependencyInjectionContainer UserModel? Я думаю, что этот путь является неправильным...

public function detailsAction() {

  $model = new UserModel($this->container);
  $model->getDetails(12345);

}
5
задан Kirzilla 9 March 2010 в 12:32
поделиться

2 ответа

Вместо того, чтобы внедрять весь контейнер DI в свои классы, вы должны внедрить только те зависимости , которые вам нужны.

Вашему UserController требуется адаптер БД (назовем этот интерфейс IDBAdapter). В C # это может выглядеть так:

public class UserController
{
    private readonly IDBAdapter db;

    public UserController(IDBAdapter db)
    {
        if (db == null)
        {
            throw new ArgumentNullException("db");
        }

        this.db = db;
    }

    public void DetailsAction()
    {
        var model = new UserModel(this.db);
        model.GetDetails(12345);
    }
}

В этом случае мы внедряем зависимость в UserModel. В большинстве случаев, однако, я склонен считать это запахом DI, если UserController принимает зависимость только для передачи его, поэтому лучшим подходом может быть использование UserController зависимости от абстрактной фабрики, подобной этой:

public interface IUserModelFactory
{
    UserModel Create();
}

В этом варианте UserController может выглядеть так:

public class UserController
{
    private readonly IUserModelFactory factory;

    public UserController(IUserModelFactory factory)
    {
        if (factory == null)
        {
            throw new ArgumentNullException("factory");
        }

        this.factory = factory;
    }

    public void DetailsAction()
    {
        var model = this.factory.Create();
        model.GetDetails(12345);
    }
}

, и вы можете определить конкретный UserModelFactory, который зависит от IDBAdapter:

public class UserModelFactory : IUserModelFactory
{
    private readonly IDBAdapter db;

    public UserModelFactory(IDBAdapter db)
    {
        if (db == null)
        {
            throw new ArgumentNullException("db");
        }

        this.db = db;
    }

    public UserModel Create()
    {
        return new UserModel(this.db);
    }
}

Это дает вам лучшее разделение задач .

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

10
ответ дан 13 December 2019 в 22:06
поделиться

Я бы использовал одноэлементный объект для всех параметров конфигурации: Вы настраиваете его в начальной загрузке, а затем решаете использовать его напрямую или передаете как параметр в ваших объектах.

Идея состоит в том, чтобы иметь один метод для извлечения данных конфигурации.

Затем вы можете предоставить абстрактный класс для манипуляций с базой данных, который использует вашу конфигурацию. singleton. DependancyInjection все еще можно использовать для переопределения данных по умолчанию.

Приведенная выше ссылка в комментарии (возможный «дубликат») завершает использование внедрения конструктора: это близко к вашему текущему методу.

Однако, если я попытаюсь понять, как работает ваша модель, я думаю, у вас будет много других классов моделей, кроме userModel. Таким образом, абстрактный класс, использующий синглтон конфигурации, может быть хорошим решением: все ваши следующие классы моделей будут просто расширять этот абстрактный класс, и вам не нужно беспокоиться о своей конфигурации.

С другой стороны, ваше решение хорошо для меня, если ваш зависимый InjectionContainer часто меняется.

0
ответ дан 13 December 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: