设计模式-适配器模式

在日常生活中,会经常遇到一些适配器,例如笔记本电脑的变压器,就是典型的电源适配器。如图8-16所示,笔记本电脑只接受15V的电压,因此不能直接和220V的电源插座连接,电源适配器能够把220V的电压转换为15V,它是连接笔记本电脑和普通电源的桥梁。
8-16
再例如,用于电话拨号上网的调制解调器(MODEM)也是一种适配器。如图8-17所示, 电脑只接受数字信号,而电话线上传输的是模拟信号,MODEM能够把模拟信号转换 为数字信号,它是连接电脑和电话网络的桥梁。
8-17

松耦合的系统之间通过接口来交互,当两个系统之间的接口不匹配时,就需要用 适配器来把一个系统的接口转换为与另一个系统匹配的接口。可见,适配器的作用是 进行接口转换。

在面向对象领域,也采用适配器模式来进行接口的转换。适配器模式有两种实现方式。

(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类的源程序。

1public class SourceImp1 implements SourceIFC{
2 public int add(int a,int b){return a+b;}
3}
4public 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的源程序。

1public 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

总的来说,组合关系比继承关系更有利于系统的维护和扩展,而且组合关系能够将多个源接口转换为一个目标接口,而继承关系只能把一个源接口转换成一个目标接口,因此应该优先考虑用组合关系来实现适配器。

下面以Hibernate使用的数据库连接池为例,介绍如何把适配器模式运用到实际项目中。一个连接数据库和Java应用的开源软件。Hibernate通过数据库连接池ConnectionPool来连接数据库。如图8-20所示,Java应用、Hibernate、ConnectionPool均为相对独立的Java软件系统。Java应用通过Hibernate API访问Hibernate的服务,Hibernate通过ConnectionPool API来访问 ConnectionPool的服务。

8-20

数据库连接池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接口
C3P0连接池的API包括
  • com.mchange.v2.c3p0.PoolConfig接口
  • com.mchange.v2.c3p0.DataSources接口
Hibernate为DBCP和C3P0连接池创建了相应的适配器,使得Hibernate能够使用这些连接池

 

8-21

如图8-21中,Hibernate只会访问ConnectionProvider接口。这个接口有3个实现类,其中DBCPConnectionProvider和C3P0ConnectionProvider类是适配器,它们分别负责把DBCP和 C3P0连接池的接口转换为ConnectionProvider接口,这两个适配器都采用组合实现方式。

DBCPConnectionProvider类的部分代码如下:

1public 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}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值