![8-16](http://hi.csdn.net/attachment/201104/26/0_1303795674y75t.gif)
![8-17](http://hi.csdn.net/attachment/201104/26/0_1303795726dyUD.gif)
松耦合的系统之间通过接口来交互,当两个系统之间的接口不匹配时,就需要用 适配器来把一个系统的接口转换为与另一个系统匹配的接口。可见,适配器的作用是 进行接口转换。
在面向对象领域,也采用适配器模式来进行接口的转换。适配器模式有两种实现方式。
(1)继承实现方式。在图8-18中,SourceIFC和TargetIFC分别代表源接口和目标接口,在SourceIFC接口中只有add(int a,int b)方法,而在目标接口中有add(int a,int b)和addOne(int a)方法,addOne(int a)方法返回 a+1 的值。TargetImp1为适配器,她实现了TargetIFC接口,并且继承SourceImp1类,从而能重用SourceImp1类的add()方法。
以下是SourceImp1类和TargetImp1类的源程序。
1 | public class SourceImp1 implements SourceIFC{ |
2 | public int add(int a,int b){return a+b;} |
3 | } |
4 | public class targetImp1 extends SourceImp1 imlements TargetIFC{ |
5 | public int addOne(int a){ |
6 | return add(a,1); |
7 | } |
8 | } |
(2)组合实现方式。在图8-19中,TargetImp1为适配器,它实现了TargetIFC接口,并且包装了SourceIFC的实现类,从而能重用SourceImp1类的add() 方法。TargetImp1类对SourceImp1类进行了包装,从而生成新的接口。采用这种实现方式的适配器模式也称之为包装类模式。
以下是TargetImp1的源程序。1 | public class TargetImp1 implement TargetIFC{ |
2 | private SourceIFC source; |
3 | public TargetImp1(SourceIFC source){ |
4 | this.source=source; |
5 | } |
6 | public int add(int a,int b){return source.add(a,b);} |
7 | public int addOne(int a){return source.add(a,1);} |
8 | } |
![8-19](http://hi.csdn.net/attachment/201104/26/0_1303795820Vh2y.gif)
总的来说,组合关系比继承关系更有利于系统的维护和扩展,而且组合关系能够将多个源接口转换为一个目标接口,而继承关系只能把一个源接口转换成一个目标接口,因此应该优先考虑用组合关系来实现适配器。
下面以Hibernate使用的数据库连接池为例,介绍如何把适配器模式运用到实际项目中。一个连接数据库和Java应用的开源软件。Hibernate通过数据库连接池ConnectionPool来连接数据库。如图8-20所示,Java应用、Hibernate、ConnectionPool均为相对独立的Java软件系统。Java应用通过Hibernate API访问Hibernate的服务,Hibernate通过ConnectionPool API来访问 ConnectionPool的服务。
![8-20](http://hi.csdn.net/attachment/201104/26/0_1303795950oRRR.gif)
数据库连接池ConnectionPool的主要功能是提供数据库连接。本章关注的并不是Hibernate和ConnectionPool的 功能及实现方式,而是介绍Hibernate和ConnectionPool这两个系统之间如何交互。Hibernate对连接池进行了抽象, 用ConnectionProvider接口作为连接池的接口。
public interface ConnectionProvider{
/**初始化数据库连接池*/
public void configure(properties props) throws HibernateException;
/**从连接池中取出一个数据库连接*/
public Connection getConnection() throws SQLException;
/**关闭参数指定的数据库连接*/
public void closeConnection(Connection conn) throws SQLException;
/**关闭数据库连接池*/
public void close() throws HibernateException;
}
Hibernate提供了连接池的实现类DriverManagerConnectionProvider,这是Hibernate默认的数据库连接池。此外,Hibernate还可以选用由第三方提供的专业数据库连接池产品,如C3P0连接池软件和DBCP连接池软件。但是这些第三方产生的连接池软件都有各自的API,它们并没有实现Hibernate制度的ConnectionProvider 接口。
例如DBCP连接池的API包括:- org.apache.commons.pool.KeyedObjectPoolFactory接口
- org.apache.commons.pool.ObjectPool接口
- com.mchange.v2.c3p0.PoolConfig接口
- com.mchange.v2.c3p0.DataSources接口
![8-21](http://hi.csdn.net/attachment/201104/26/0_1303795989weHh.gif)
如图8-21中,Hibernate只会访问ConnectionProvider接口。这个接口有3个实现类,其中DBCPConnectionProvider和C3P0ConnectionProvider类是适配器,它们分别负责把DBCP和 C3P0连接池的接口转换为ConnectionProvider接口,这两个适配器都采用组合实现方式。
DBCPConnectionProvider类的部分代码如下:
1 | public class DBCPConnectionProvider implements Connectionprovider{ |
2 | private Integer isolation; |
3 | private DataSource ds; |
4 | private keyedObjectPoolFactory statementPool; |
5 | private ObjectPool connectionPool; |
6 | public Connection getConnection()throws SQLException{ |
7 | final Connection c=ds.getConnection(); |
8 | if(isolation!=null)c.setTransactionIsolation(isolation.intValue() ); |
9 | if( c.getAutoCommit() ) c.setAutoCommit(false); |
10 | return c; |
11 | } |
12 | public void colseConnection(Connection conn) throws SQlException{ |
13 | conn.colse(); |
14 | } |
15 | public void colse()throws HibernateException{ |
16 | try{ |
17 | connectionPool.close(); |
18 | } |
19 | catch(Exception e){ |
20 | throw new HibernateException("could not close DBCP pool",e); |
21 | } |
22 | } |
23 | } |