Реализация подкачки во время выполнения для Dagger предоставила зависимость

Используя Dagger 2, у меня есть объект домена, который я предоставляю докладчикам. Этот объект домена зависит от репозитория. Этот репозиторий имеет две реализации, но обе реализуют один и тот же интерфейс. Мне нужно как-то настроить кинжал для переключения между двумя реализациями репозитория во время выполнения на основе выбора пользователем опции «Демонстрационный режим».

Итак, у меня есть следующий объект домена:

public class SomeAwesomeBusinessLogic {

    Repository repository;

    @Inject
    public SomeAwesomeBusinessLogic(Repository repository) {
        this.repository = repository;
    }
    //awesome stuff goin down
}

И два репозитория:

public RemoteRepository implements Repository {

    @Inject
    public RemoteRepository() {
        //setup
    }
}

public DemoRepository implements Repository {

    @Inject
    public DemoRepository() {
        //setup
    }
}

Любые идеи о том, как структурировать мои модули и компоненты, чтобы заставить это работать?


person akahappy    schedule 16.03.2017    source источник


Ответы (1)


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

@Module
public class RepositoryModule {
  private final boolean isDemo;

  public RepositoryModule(boolean isDemo) {
    this.isDemo = isDemo;
  }

  @Provides
  public Repository providesRepository() {
    return isDemo? new DemoRepository() : new RemoteRepository();
  }
  // Other providers
}

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

public interface RepositoryFactory {
   Repository getRepository(Configuration configuration);
}

public class RepositoryFactoryImpl implements RepositoryFactory {

   @Inject
   public RepositoryFactoryImpl() {}

   // The implementation
}

@Module
public class RepositoryModule {
  @Provides
  public RepositoryFactory providesRepositoryFactory(
            RepositoryFactoryImpl factory) {
    return factory;
  }
  // Other providers
}

Configuration будет простым POJO, в котором вы можете указать несколько атрибутов для настройки вашего репо. Скажите, например:

public class Configuration {
   private final boolean isDemo;
   // all the POJO stuff you need
}

Затем вы можете сделать свой объект домена зависимым от фабрики:

public class SomeAwesomeBusinessLogic {

   private final RepositoryFactory repositoryFactory;

   @Inject
   public SomeAwesomeBusinessLogic(
                RepositoryFactory repositoryFactory) {
      this.repositoryFactory = repositoryFactory;
   }
   //awesome stuff going down
}

Затем вы можете сделать repositoryFactory.getRepository(new Configuration(true/false)); в своей бизнес-логике.

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

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

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

Надеюсь это поможет

person Fred    schedule 20.03.2017