科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件无废话C#设计模式之三:Abstract Factory

无废话C#设计模式之三:Abstract Factory

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本系列文章将向大家介绍一下C#的设计模式,此为第三篇文章,相信对大家会有所帮助的。废话不多说,继续来看。

作者:LoveCherry 来源:博客园 2007年11月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
代码说明

  PatrixSceneFactory就是一个抽象工厂,它声明了创建抽象的场景以及抽象的纹理的接口。(广告时间:Patrix是我公司的一款休闲FPS游戏,详细请见http://www.qwd1.com)

  Model和Texture是抽象产品。在Model类中有一个抽象方法,用于为模型填充纹理。

  HalfPaper和Matrix是具体工厂,它用于创建某个场景的模型和纹理。(你可能对两个类的名字不太理解,其实HalfPaper和Matrix是两个地图的名字)

  xxxModel和xxxTexture就是具体的产品了。它们就是针对某个场景的模型和纹理,具体工厂负责创建它们。

  Patrix这个类负责加载场景,为了避免加载不同场景使用case语句,在这里我们使用反射来加载具体工厂类。

  可以看到,一旦有了新的场景(或者说地图),我们只需要设计新的xxxModel和xxxTexture以及具体工厂类就可以了,加载场景的那部分代码(也就是Patrix类)不需要做改动。

  我们现在这个游戏可是不支持和电脑对战的,万一以后需要支持电脑了,那么场景中的元素除了纹理和模型之外就还需要加电脑了。也就是说抽象工厂还需要多生产一种类型的产品,这个时候抽象工厂就无能为力了。抽象工厂只能解决系列产品扩张的变化点(在我们的例子中就是地图的新增),因此千万把抽象工厂所能生产的产品考虑周全了。

  何时采用

  从代码角度来说,你希望在统一的地方创建一系列相互关联的对象,并且基于抽象对象的时候。

  从应用角度来说,如果你的产品是成组成套的,并且肯定会不断扩展新系列的,那么就适用抽象工厂。比如说,外面买的塑料模型,里面总是有图纸、模型元件板和外壳包装三部分。那么生产模型的厂就是抽象工厂,打印图纸、打印包装盒以及生产元件板的三个流水线就是具体工厂了。需要生产新的模型,只需要制作新的图纸输入到三个流水线的电脑中就可以了。

  实现要点

  抽象工厂本身不负责创建产品,产品最终还是由具体工厂来创建的。比如,MatrixModel是Matrix创建的,而不是PatrixSceneFactory创建的。在.NET中可以使用反射来创建具体工厂,从而使得代码变动降到最低。

  在抽象工厂中需要体现出生产一系列产品。这一系列产品是相互关联,相互依赖一起使用的。

  抽象工厂对应抽象产品,具体工厂对应具体产品,外部依赖抽象类型,这样对于新系列产品的创建,外部唯一依赖的就是具体工厂的创建过程(可以通过反射解决)。

  注意事项

  一般来说需要创建一系列对象的时候才考虑抽象工厂。比如,创建一个场景,需要创建模型和纹理,并且模型和纹理之间是有一定联系的,不太可能把PatrixTexture套用在MatrixModel上。

  如果系统的变化点不在新系列的扩充上,那么就没有必要使用抽象工厂。比如,如果我们不会增加新地图的话,那么也就没有必要引入抽象工厂。

  .NET中的抽象工厂

  我们说过,抽象工厂针对系列产品的应变。在使用ADO.NET进行数据访问的时候,如果目标数据库是Access,我们会使用OleDbConnection、OleDbCommand以及OleDbDataAdapter等一系列ADO.NET对象。那么如果数据库是SQL Server,我们又会改用SqlConnection、SqlCommand以及SqlDataAdapter等一系列ADO.NET对象。如果只使用一套对象,没有什么大问题,如果我们的数据访问有系列变化的需求,比如可以针对Access和SQL Server,而且希望改换数据库尽量对客户端代码透明,那么就需要引入抽象工厂模式

  好在,ADO.NET 2.0中已经有了整套抽象工厂的类型。看下面的代码,你应该能辨别这些类型在抽象工厂中的角色:

以下是引用片段:
  public abstract class DbProviderFactory
  {
  // Methods
  protected DbProviderFactory()
  {
  }
  public virtual DbCommand CreateCommand()
  {
  return null;
  }
  public virtual DbCommandBuilder CreateCommandBuilder()
  {
  return null;
  }
  public virtual DbConnection CreateConnection()
  {
  return null;
  }
  public virtual DbConnectionStringBuilder CreateConnectionStringBuilder()
  {
  return null;
  }
  public virtual DbDataAdapter CreateDataAdapter()
  {
  return null;
  }
  public virtual DbDataSourceEnumerator CreateDataSourceEnumerator()
  {
  return null;
  }
  public virtual DbParameter CreateParameter()
  {
  return null;
  }
  public virtual CodeAccessPermission CreatePermission(PermissionState state)
  {
  return null;
  }
  // Properties
  public virtual bool CanCreateDataSourceEnumerator
  {
  get
  {
  return false;
  }
  }
  }
  public sealed class OleDbFactory : DbProviderFactory
  {
  // Fields
  public static readonly OleDbFactory Instance = new OleDbFactory();
  // Methods
  private OleDbFactory()
  {
  }
  public override DbCommand CreateCommand()
  {
  return new OleDbCommand();
  }
  public override DbCommandBuilder CreateCommandBuilder()
  {
  return new OleDbCommandBuilder();
  }
  public override DbConnection CreateConnection()
  {
  return new OleDbConnection();
  }
  public override DbConnectionStringBuilder CreateConnectionStringBuilder()
  {
  return new OleDbConnectionStringBuilder();
  }
  public override DbDataAdapter CreateDataAdapter()
  {
  return new OleDbDataAdapter();
  }
  public override DbParameter CreateParameter()
  {
  return new OleDbParameter();
  }
  public override CodeAccessPermission CreatePermission(PermissionState state)
  {
  return new OleDbPermission(state);
  }
  }
  public sealed class SqlClientFactory : DbProviderFactory, IServiceProvider
  {
  // Fields
  public static readonly SqlClientFactory Instance = new SqlClientFactory();
  // Methods
  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);
  }
  object IServiceProvider.GetService(Type serviceType)
  {
  object obj2 = null;
  if (serviceType == GreenMethods.SystemDataCommonDbProviderServices_Type)
  {
  obj2 = GreenMethods.SystemDataSqlClientSqlProviderServices_Instance();
  }
  return obj2;
  }
  // Properties
  public override bool CanCreateDataSourceEnumerator
  {
  get
  {
  return true;
  }
  }
  }

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章