Инъекции зависимостей и услуги локатор/контейнер


Я реализовал чистый архитектуры для моего приложения и у меня есть несколько вопросов.

Как правило, чисто Ди-спорили за образец локатора службы, потому что это очень явное и более проверяемым.

Однако, мне нравится идея иметь объект, который содержит все мои услуги или все мои репозитории (контейнер), и я могу только вставить, что один объект вместо того, чтобы впрыскивать различные услуги/хранилищ для простоты развития.

Но я не уверен, если это все-таки следует твердые принципы.

Например, вот типичный Ди:

// Database

type Database interface {
    Insert(...)
    Delete(...)
}

// User object

type User struct {}

// User Service

type UserService interface {
    Create(user User)
}

func NewUserService(userRepo UserRepository) UserService {
    return &userService{userRepo: userRepo}
}

type userService struct {
    userRepo UserRepository
}

func (s *userService) Create(user User) {
    s.userRepo.Create(user)
}

// User Repository

type UserRepository interface {
    Create(user User)
}

func NewUserRepository(db Database) UserRepository {
    return &userRepository{db: db}
}

type userRepository struct {
    db Database
}

func (r *userRepository) Create(user User) {
    r.db.Insert(user)
}

main() {
    // Create db
    db := database.New(...)

    // Create repo by injecting db
    userRepo := NewUserRepository(db)

    // Create service by injecting repo
    userService := NewUserService(userRepo)
}

Как вы видите в примере выше, что это чисто Ди подхода.

Проблема у меня с этим доводы может получить более 30 вещей, впрыскивается в более крупное приложение.

Поэтому я придумал другой шаблон, который является в основном впрыснуть один ServiceFactory или RepositoryFactoryи тех, кто будет содержать указатели на все другие, более зернистый услуги/репозиторий классов.

Так что новый кодекс может быть изменен на что-то вроде этого:

// User Service

type UserService interface {
    Create(user User)
}

func NewUserService(repos RepositoryFactory) UserService {
    return &userService{repos: repos}
}

type userService struct {
    repos RepositoryFactory
}

func (s *userService) Create(user User) {
    s.repos.UserRepository.Create(user)
}

// Repository factory

type RepositoryFactory struct {
    UserRepository UserRepository
}

func NewRepositoryFactory(db Database) RepositoryFactory {
    return RepositoryFactory{
        UserRepository: NewUserRepository(db),
    }
}

main() {
    // Create db
    db := database.New(...)

    // Create repo factory
    repos := NewRepositoryFactory(db)

    // Create services by injecting repo factory
    userService := NewUserService(repos)
    fooService := NewFooService(repos)
    barService := NewBarService(repos)
    bazService := NewBazService(repos)
}

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

Вы рекомендовали бы этот подход, почему/почему нет? Спасибо.



335
0
задан 7 марта 2018 в 03:03 Источник Поделиться
Комментарии