装饰模式
2018-11-05 本文已影响0人
小牛长成记
二、装饰模式
2.1 装饰模式原理Connection close
目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
口诀:
1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
2、定义一个被包装类类型的成员变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
5、对于需要改写的方法,写自己的代码。
1.包装Connection的实现类
//mysql的Connection类实现了sun公司的Connection的接口规范
//我们要包装的是mysql的Connection
//所以:我们写的这个包装类也要实现sun公司的Connection的接口规范--我们的类与mysql的Connection要具有相同的约束动作
//1.编写一个类,使之与被包装类实现相同的接口(具有相同的行为)
public class DecoratorConnection implements Connection{
private Connection oldConnection; //2.添加一个被包装类的对象(依赖的关系)--实际上运行的时候传过来的是实现类的对象:com.mysql.jdbc.Connection的实例
private LinkedList<Connection> pool;
//3.定义构造方法,通过构造方法的参数,将被包装类注入,给被包装类赋值
//实际上运行的时候传过来的是实现类的对象:com.mysql.jdbc.Connection的实例
public DecoratorConnection(Connection conn,LinkedList<Connection> pool){
this.oldConnection = conn;
this.pool = pool;
}
//5.需要改写的方法:自己写代码
@Override
public void close() throws SQLException {
//因为这里关闭连接也需要连接池的引用,所以,也必须把连接池注入到本类中
pool.addLast(oldConnection);
}
//下面的方法不需要改变原有的功能,只以prepareStatement(String sql)为例,以下其它方法相同:
//4.对于不需要改写的方法,调用原有的方法
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return oldConnection.prepareStatement(sql);
}
//其它方法略……
}
2.连接池产生的Connection是被包装之后的类
//sun公司开发一套连接池的接口规范DataSource,自定义的连接池,要实现这个规范
//这回实现连接池,使用的是实现sun公司的接口
public class MyDataSource implements DataSource{
// 创建一个连接的池子--集合,线程安全的问题
private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections
.synchronizedList(new LinkedList<Connection>());
// 在连接池中初始化10个连接
static {
try {
for (int i = 0; i < 10; i++) {
Connection conn = DBUtil.getConnection();
pool.add(conn);
}
} catch (Exception e) {
// 将异常向上抛
throw new ExceptionInInitializerError("初始化连接池失败!");
}
}
// 重写getConnection()方法
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
if(pool.size()>0){ //说明池子里还有连接
conn = pool.removeFirst(); //移除并返回对象
Connection myConn = new DecoratorConnection(conn,pool); //得到一个包装后的Connection对象
return myConn; //返回的是包装之后的Connection
}else{
throw new RuntimeException("服务器正忙.......");
//服务器正忙的解决思路:
//1.等待
//2.等待超时新创建一个连接用DBUtil产生,用完之后,不用交回池,真的close()
}
}
// 其余方法实现……
@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
3.编写测试类
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
try {
DataSource ds = new MyDataSource();
conn = ds.getConnection(); //从池中取出一个连接,这个连接已经被包装了DecoratorConnection类型的
ps = conn.prepareStatement(".........");
ps.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close(); //调用了包装Connection之后的DecoratorConnection的close()方法了
//即:被连接池回收了
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}