Как указать, какую реализацию интерфейса возвращать, основываясь на каком-либо флаге / аргументе? - PullRequest
0 голосов
/ 27 мая 2010

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

  • Бизнес-данные (заказы, продукция, категории и т. д.)
  • Метаданные (данные о структура бизнес-данных)
  • Данные пользователя (пользовательские настройки сохранены артефакты и т. д.)

Детали данных не важны ... это просто три базы данных. Во всем приложении вы хотите подключиться к этим трем и вернуть реализацию IDbConnection . Реализация, используемая для пользовательских данных, может немного отличаться от реализации, используемой для бизнес-данных и так далее. Строки подключения для каждого находятся в файле конфигурации.

Итак, мы рассмотрели несколько подходов, в том числе:

Фабрика с несколькими методами

class ConnectionFactory {

  public static IDbConnection CreateBusinessDataConnection()
  {
    // 
  }

  public static IDbConnection CreateMetadataConnection()
  {
    //
  }

  public static IDbConnection CreateUserDataConnection()
  {
    //
  }
}

... в этом примере, однако, мы могли бы также возвратить конкретную реализацию, а не ссылку IDbConnection . Недостатком является то, что мы не можем изменить тип используемого соединения без изменения кода потребителя позже.

Фабрика с одним методом

В этом случае мы используем один метод и передаем некоторое значение (вероятно, enum), чтобы указать, какой тип соединения мы хотим:

enum DbConnectionType { BusinessData, Metadata, UserData }

class ConnectionFactory {

  public static IDbConnection CreateDataConnection(DbConnectionType connType)
  {
    // look at connType and probably use a switch statement to create 
    // the connection for that type.
  }
}

У них обоих есть свои плюсы и минусы ... чтобы добавить к миксу, мы недавно начали использовать контейнер Unity IoC от Microsoft в проекте. Кажется, что это может быть ценно здесь, но это в начале нашего понимания. На первый взгляд, это не похоже на то, что это помогает нам, потому что мы не регистрируем конкретный тип.

container.Register(IDbConnection, [ which of the three implementations ? ]);

Вместо этого больше похоже на то, что мы говорим "Когда я запрашиваю IDbContainer и также предоставляю вам это значение перечисления, пожалуйста, верните ЭТУ реализацию IdbConnection." Мы еще не нашли способ сделать это в Unity (но, опять же, это все еще ново для нас, и мы работаем с образцами).

Мысли

Ответы [ 3 ]

2 голосов
/ 27 мая 2010

Второй вариант мне кажется наиболее подходящим (хотя первый почти не отличается). Преимущество этого состоит в том, что единственный код, который должен знать или думать о том, к какой базе данных подключаться, это код, который вызывает ConnectionFactory - все остальное может просто использовать общий интерфейс IDBConnection.

1 голос
/ 03 июня 2014

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

Затем зарегистрируйте каждую из реализаций фабрики соединений как именованный тип в Unity.

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

0 голосов
/ 29 мая 2010

Поместите методы первого дизайна в тело метода второго дизайна. Затем вы реализуете экземпляр шаблона проектирования Factory.

...