装饰模式

二、装饰模式
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 pool; //3.定义构造方法,通过构造方法的参数,将被包装类注入,给被包装类赋值 //实际上运行的时候传过来的是实现类的对象:com.mysql.jdbc.Connection的实例 public DecoratorConnection(Connection conn,LinkedList 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 pool = (LinkedList) Collections .synchronizedList(new LinkedList()); // 在连接池中初始化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(); } } }

    推荐阅读