【问题标题】:How to indicate which implementation of an interface to return, based on some flag/argument?如何根据某些标志/参数指示要返回的接口的哪个实现?
【发布时间】:2010-05-27 16:24:28
【问题描述】:

在具有多个支持它的数据库的分布式应用程序中,我们正在寻找更好的方法来处理数据库连接的创建。例如,假设您的系统后面有三个数据库:

  • 业务数据(订单、产品、 类别等)
  • 元数据(关于 业务数据的结构)
  • 用户数据(用户首选项,已保存 人工制品等)

数据的细节并不重要……它只是三个数据库。在整个应用程序中,您希望获得与这三个的连接并返回一个 IDbConnection 实现。用于用户数据的实现可能与用于业务数据的实现略有不同。等等。每个连接字符串都在一个配置文件中。

所以我们研究了几种方法,包括:

具有多种方法的工厂

class ConnectionFactory {

  public static IDbConnection CreateBusinessDataConnection()
  {
    // 
  }

  public static IDbConnection CreateMetadataConnection()
  {
    //
  }

  public static IDbConnection CreateUserDataConnection()
  {
    //
  }
}

... 不过,在这个例子中,我们也可以返回一个特定的实现而不是 IDbConnection 引用。缺点是我们无法在不更改消费者代码的情况下更改所使用的连接类型。

单一方法的工厂

在这种情况下,我们使用单个方法并传入一些值(可能是枚举)来指示我们想要的连接类型:

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.
  }
}

这些都有优点和缺点...此外,我们最近开始在项目中使用 Microsoft 的 Unity IoC 容器。看起来这在这里可能很有价值,但它还处于我们理解的早期阶段。从表面上看,它似乎对我们没有帮助,因为我们没有注册具体类型。

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

相反,它更像是我们在说“当我请求一个 IDbContainer 并且我还为你提供了这个枚举值时,请返回这个 IdbConnection 的实现。” 我们还没有找到一个在 Unity 中执行此操作的方法(但同样,它对我们来说仍然是新的,我们正在研究示例)。

想法?

【问题讨论】:

  • 如果客户需要知道要建立哪种类型的连接,为什么要对他隐瞒呢?数据库的使用是否相同,即非常相似的模式?
  • 对于这个特定的示例,理想情况下客户端不知道正在使用哪种类型的连接实现。我们正在使用一个开源数据库,其中有多个具有不同优点/缺点的提供商。因此,对于某些连接,我们可能会选择速度较慢但功能更多的提供商……其他人会使用速度最快的提供商。问题更多地在于采用的一般设计方法 - 给定一个通用接口,如何根据某些标志/条件/指标来决定使用哪个实现。枚举、switch 语句、某种类型的 DI 或 IoC 方法等。谢谢。

标签: c# design-patterns oop interface unity-container


【解决方案1】:

第二个变体在我看来最好(虽然第一个几乎没有什么不同)。这样做的好处是,唯一需要知道或考虑要连接到哪个数据库的代码是调用ConnectionFactory 的代码——其他一切都可以使用通用的IDBConnection 接口。

【讨论】:

    【解决方案2】:

    假设您的应用程序的特定实例将为每种数据库类型使用相同类型的连接(即每个应用程序一个提供程序),您可以为每个不同的连接提供程序实现类并使 ConnectionFactory 成为接口.

    然后将每个连接工厂实现注册为 Unity 中的命名类型。

    当应用程序解析连接工厂时,您可以将提供程序定义为配置文件中的设置,这样如果他们以后更改提供程序,则无需重新编码。

    【讨论】:

    • Steve - 已经有一段时间了,所以我忘记了这个问题。但是,您的答案与我最终采用的方法非常接近。感谢您的参与 - 它促使我重新审视它。
    【解决方案3】:

    将第一个设计的方法放入第二个设计的方法体中。然后,实现工厂设计模式的一个实例。

    【讨论】:

    • Paul... 我不清楚这与第二个代码块中的方法存根中建议的内容有何不同 - 也就是说,它会有一个开关或其他一些结构决定返回哪个。所以使用工厂很清楚 - 我想问题更多地围绕着工厂如何决定返回哪个实例。有很多方法可以做到这一点,但我想知道是否有比简单地传入枚举和使用 switch/case 更好/更优雅的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多