相对前面的工厂、创建者模式而言,适配器模式的变化主要体现在Adapter类型上,因为对客户程序而言,它需要的抽象接口ITarget是固定 的,您只须告诉它用哪个实现了ITarget的类型即可,额外的可能需要把Adapter的一些执行参数配置上去即可。我们看一个现成的例子:.NET Framework中关于Data Provider的设置。
首先,在Machine.Config中有个名为<system.data>的ConfigurationSection,它的下面有 一个名为<DbProviderFactories>的节点(ConfigurationElemeentCollection),它登记了 每个DbProvider的逻辑名称和具体的Qualified名称,其代码如下:
Machine.Config |
然后,我们在应用中选择需要的DbProvider,这其实相当于选择适合某个特定数据库的一组符合DbConnection、 DbDataAdapter、DbCommand、DbTransaction……要求的Adapter类型,由于它们是"一系列相关或具有依赖关系 的",所以没有直接返回具体的SqlConnection、SqlCommand,而是返回了一个抽象工厂,由这个工厂加工具体的适配器,其代码如下。
App.Config |
其实ADO.NET 2.0的配置给了我们一个不错的适配器类型配置思路,总结如下:
首先,客户程序明确自己需要的接口ITarget。
设计App.Config(或Web.Config,有可能还会涉及Machine.Config)的结构,考虑到扩展和需要,可以把这个配置部分设计为一个ConfigurationElementCollection,可以动态增加。
考虑Adapter还需要调整哪些特性,比如数据访问中的Package Size之类的参数,如果参数的数量和结构非常稳定,可以设计为每个ITarget配置节点下面的子ConfigurationElement,但如果不 同ITarget类型需要的参数数量不同,内容也不一定,则在每个ITarget节点下增加一个 ConfigurationElementCollection。
我们完成或采购第三方实现ITarget的类库。
为这些类库里面实现了ITarget的类型起一个逻辑名称,并把它们的Quanlified名称登记在每个ITarget的ConfigurationElement中,相关的参数顺次登记在子节点中。
按照我们在创建型模式已经介绍的方法,增加一个工厂类,按照逻辑名称创建ITarget。
您也可以把认为"固定"的参数定义在ITarget的ConfigurationElement上,不过除非是非常必要而且固定的,否则还是算了。把一个Name/Value Pair传递给具体Adapter,后者将酌情办理。
为什么要给每个具体Adapter起个逻辑名称呢?这是为了让你的应用能与具体的Adaptee有效隔离,比如您的业务是操作销售数据,那么开发最 好基于一个名为"Sales"的逻辑数据库,至于系统上线后,把它放在ORACLE里还是SQL Server里,放在哪台服务器上,进行配置即可,当然您的应用首先要使用通用的SQL标准完成。)