详解C#的设计模式编程之抽象工厂模式的应用

2019-12-26 18:01:29王振洲

 

抽象工厂模式的定义和类图

抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么。这样客户就可以从具体产品中被解耦。下面通过抽象工模式的类图来了解各个类中之间的关系:

详解C#的设计模式编程之抽象工厂模式的应用

抽象工厂的分析
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展,这真是抽象工厂模式的优点所在,然后抽象模式同时也存在不足的地方。下面就具体看下抽象工厂的缺点(缺点其实在前面的介绍中以已经涉及了):

抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。

知道了抽象工厂的优缺点之后,也就能很好地把握什么情况下考虑使用抽象工厂模式了,下面就具体看看使用抽象工厂模式的系统应该符合那几个前提:

一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
这个系统有多个系列产品,而系统中只消费其中某一系列产品
系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。


.NET中抽象工厂模式实现
抽象工厂模式在实际中的应用也是相当频繁的,然而在我们.NET类库中也存在应用抽象工厂模式的类,这个类就是System.Data.Common.DbProviderFactory,这个类位于System.Data.dll程序集中,该类扮演抽象工厂模式中抽象工厂的角色,我们可以用reflector反编译工具查看该类的实现:


/// 扮演抽象工厂的角色
/// 创建连接数据库时所需要的对象集合,
/// 这个对象集合包括有 DbConnection对象(这个是抽象产品类,如绝味例子中的YaBo类)、DbCommand类、DbDataAdapter类,针对不同的具体工厂都需要实现该抽象类中方法,
public abstract class DbProviderFactory
{
  // 提供了创建具体产品的接口方法
  protected DbProviderFactory();
  public virtual DbCommand CreateCommand();
  public virtual DbCommandBuilder CreateCommandBuilder();
  public virtual DbConnection CreateConnection();
  public virtual DbConnectionStringBuilder CreateConnectionStringBuilder();
  public virtual DbDataAdapter CreateDataAdapter();
  public virtual DbDataSourceEnumerator CreateDataSourceEnumerator();
  public virtual DbParameter CreateParameter();
  public virtual CodeAccessPermission CreatePermission(PermissionState state);
}
DbProviderFactory类是一个抽象工厂类,该类提供了创建数据库连接时所需要的对象集合的接口,实际创建的工作在其子类工厂中进行,微软使用的是SQL Server数据库,因此提供了连接SQL Server数据的具体工厂实现,具体代码可以用反编译工具查看,具体代码如下:

/// 扮演着具体工厂的角色,用来创建连接SQL Server数据所需要的对象
public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
{
  // Fields
  public static readonly SqlClientFactory Instance = new SqlClientFactory();
  // 构造函数
  private SqlClientFactory()
  {
  }
      
  // 重写抽象工厂中的方法
  public override DbCommand CreateCommand()
  { // 创建具体产品
    return new SqlCommand();
  }
  public override DbCommandBuilder CreateCommandBuilder()
  {
    return new SqlCommandBuilder();
  }
  public override DbConnection CreateConnection()
  {
    return new SqlConnection();
  }
  public override DbConnectionStringBuilder CreateConnectionStringBuilder()
  {
    return new SqlConnectionStringBuilder();
  }
  public override DbDataAdapter CreateDataAdapter()
  {
    return new SqlDataAdapter();
  }
  public override DbDataSourceEnumerator CreateDataSourceEnumerator()
  {
    return SqlDataSourceEnumerator.Instance;
  }
  public override DbParameter CreateParameter()
  {
    return new SqlParameter();
  }
  public override CodeAccessPermission CreatePermission(PermissionState state)
  {
    return new SqlClientPermission(state);
  }
}