.NET2.0 框架中的 AbstractFactory 模式

    由于最近有了宝宝,导致夜里写文章的时间越来越短,而白天又忙于开发。没办法,只有挤时间去写东西了。
前些天在园子里看到了这篇文章,http://www.cnblogs.com/Yahong111/archive/2007/07/18/822946.html,对里
面写的内容浏览了一下,这里首先对作者的实践精神表示赞赏。我这里只是从别的角度阐述一下AbstractFactory
在这种应用场景下的发展,内容不多,希望大家见谅。

    1. DbService 是我看到的第一个使用抽象工厂模式设计的数据库链接类。其实在几年前网上就有人写了这个
东西,代码不多,但应用的背景和设计思路与永红(http://www.cnblogs.com/Yahong111/archive/2007/07/18/822946.html)
的思路非常相似。大家可以去网上搜一搜就知道了。
 
    2. 微软也采用了这种模式在他们的NET2.0框架中。我甚至可以对NET2.0中的新添的一些类与模式文章中类内
容对号入座。只要大家Reflector看一下.NET2.0框架代码即可。为了清楚起见,我只在这里做一下简单说明,旨在
抛砖引玉。

    System.Data.Common.DbProviderFactory, 位置在System.Data.dll中。注意这是一个 抽象类
   
    public abstract class DbProviderFactory
    {   
        // Methods
        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);

        // Properties
        public virtual bool CanCreateDataSourceEnumerator { get; }
    }

    这个类在Abstract Factory模式下就是AbstractFactory,也就是永红所说的那个DbInterfaceGenerator接口。但
为什么微软要用抽象类而不是接口(本身也偏向于使用接口),也只有微软才知道了:)。
    目前我的理解是减少基类中一些不必要的实现代码或进行条件判断时(如为 null),有相关的返回值进行比较
如下:
    public virtual DbCommand CreateCommand()
    {
            return null;
    }


 
    这个函数就是DbProviderFactory类的一个虚方法,这个方法会在子类中将被重写, 而子类(SqlClientFactory)
中的代码类内容如下(位于System.Data.SqlClient.SqlClientFactory)

    public sealed class SqlClientFactory : DbProviderFactory
    {
        // Fields
        public static readonly SqlClientFactory Instance;

        // Methods
        static SqlClientFactory();
        private SqlClientFactory();
        public override DbCommand CreateCommand()
        {
        return new SqlCommand();
            }

        public override DbCommandBuilder CreateCommandBuilder()...
        public override DbConnection CreateConnection()
        {
        return new SqlConnection();
        }

        public override DbConnectionStringBuilder CreateConnectionStringBuilder()...
        public override DbDataAdapter CreateDataAdapter();
        public override DbDataSourceEnumerator CreateDataSourceEnumerator()...

        public override DbParameter CreateParameter()
        {
        return new SqlParameter();
        }

 

        public override CodeAccessPermission CreatePermission(PermissionState state);

        // Properties
        public override bool CanCreateDataSourceEnumerator { get; }
    }

    看到这里大家应该明白一些了吧。顾名思议,SqlClientFactory就是AbstractFactory模式图中的
ContreateFactory1类 ,对应永红的图中的SqlDbInterface接口。另外大家也可以从ORACLE,MySql官方
下载最新的DLL,反射里面的OracleClientFactory和MySqlClientFactory代码,大家会看到DLL中的相关方
法“模样”大同小异。

     注:为了使用这个DbProviderFactory类,微软还出了一些辅助类,如:
          DbParameter 继承自 IDataParameter   
          DataAdapter 继承自 IDataAdapter
          DbDataAdapter    继承自 IDbDataAdapter 
          DbDataReader 继承自  IDataReader

     并且这些类基本都是抽象类:)

     说到这里,可能有人要说了,微软这么做到底是图什么呀!原有的接口在那呆的挺好,大家只要继承
并实现里面想要的功能部份就行了。其实这里恰恰巧说明了微软的“聪明”之外,不知道大家看到没有,在
前些年JAVA社区还在讨论框架,AOP , IOC 时,Microsoft官方似乎反应比较“冷淡”,但如今天我们从.net
2 以及 .net3看到了对于AOP和很多精典框架模式的嵌入,这里有从JAVA类库思想中得来的经验,也有开源
社区的“贡献”。微软恰恰在上述的那些理论或代码框架成功(甚至有成功案例)情况下快速加入这些东西,
这不能不说微软很“聪明”。  不好,又跑题了:)

      3.因为最近公司的产品在向.net2 框架过度,所以就出现了这么一个问题:如果产品要在这两个框架都
能顺利运行,同时还要体现.net2 的一些“新”的优势,那只有写两个"不同"的链接类。其中一个用到了上面
的那个DbProviderFactory类,而在.net1 下基本采用接口,参考DbService,同时为了保证两套代码的逻辑对
应关系,我简单的实现了SqlClientFactory等在2.0框架中才有的类。实现的方法参见.net2的相关类代码(本
人采用同名方式引入了这几个类)。另外关于使用实现我们也采取“反射”方式。这与永红所想的方法是“
不谋而合”了 :)

    说到这里,有一个现象我想再谈谈我的看法,以前看设计模式只有从开源的框架,技术社区或别人的源码
中分析。其实当我们还在为找出精典的应用设计模式的代码(net版本)而苦苦搜索时,微软已经给我们打开了
一个新的“窗口”,那就是.net 框架本身。这个与我们朝夕相伴的家伙其实就是一个非常好的学习设计模式
的例子。虽然.net 框架推陈出新的速度让人只能用"惊叹"来形容,但模式这种东西在里面却安然无恙,必定
这是框架的骨头呀。所以我希望大家多挖.net框架的代码,这会使我们的程序设计水平有长足的提高。

附:
    Oracle数据库的接口  http://www.oracle.com/technology/software/tech/windows/odpnet/index.html
    MySql 数据库的接口  http://dev.mysql.com/downloads/connector/net/5.0.html

    另外我们的公司的产品是开源的,大家可以在我们在2.0版本看到上面我所说的实现方式。

    我们的网址是: http://nt.discuz.net

    就先贫到这里了......
 
参考文章:

    永红 http://www.cnblogs.com/Yahong111/archive/2007/07/18/822946.html


posted @ 2007-07-23 13:54  代震军  阅读(5116)  评论(8编辑  收藏  举报