装饰模式

二、装饰模式

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();
        }
    }
}

你可能感兴趣的:(装饰模式)