装饰设计模式与面向接口编程的一应用案例

2019-04-29  本文已影响0人  衣忌破

首先先了解 装饰设计模式和面向接口编程的一般定义。

装饰设计模式

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

面向接口编程

在一个[面向对象]的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对[系统设计]人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

下面以自定义数据库连接池为例具体说明这两概念。

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class ConnectionWrap  implements Connection{
    
    Connection connection = null;
    List <Connection> list ;
    public ConnectionWrap(Connection connection , List <Connection> list) {
        super();
        this.connection = connection;
        this.list = list;
    }

    @Override
    public void close() throws SQLException {
        //connection.close();
        System.out.println("有人来归还连接对象了。 归还之前,池子里面是:"+list.size());
        list.add(connection);
        System.out.println("有人来归还连接对象了。 归还之后...,池子里面是:"+list.size());
    }
    
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }
    //下面还有许多方法为了方便说明 都先省略。。。
}

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.sql.DataSource;

/**
 * 这是一个数据库连接池
 * 一开始先往池子里面放10个连接
 * 
 *  1. 开始创建10个连接。
 * 
 *  2. 来的程序通过getConnection获取连接
 * 
 *  3. 用完之后,使用addBack 归还连接。
 * 
 *  4. 扩容。 
 * 
 * 
 * 问题: 
 * 
 *      1. sun公司针对数据库连接池定义的一套规范。 
 *  
 *  1. 需要额外记住 addBack方法
 * 
 *  2. 单例。
 * 
 *  3. 无法面向接口编程。 
 * 
 *      UserDao dao = new UserDaoImpl();
 *      dao.insert();
 * 
 * 
 *      DataSource dataSource = new MyDataSource();
 * 
 *      因为接口里面没有定义addBack方法。 
 * 
 *  4. 怎么解决?  
 *      
 */
public class MyDataSource implements DataSource {
    
    List <Connection> list = new ArrayList<Connection>();
    
    public  MyDataSource() {
        for (int i = 0; i < 10; i++) {
            Connection conn = JDBCUtil.getConn();
            list.add(conn);
        }
    }
    
    
//  该连接池对外公布的获取连接的方法
    @Override
    public Connection getConnection() throws SQLException {
        //来拿连接的时候,先看看,池子里面还有没有。
        if(list.size() == 0 ){
            for (int i = 0; i < 5; i++) {
                Connection conn = JDBCUtil.getConn();
                list.add(conn);
            }
        }
        
        //remove(0) ---> 移除第一个。 移除的是集合中的第一个。  移除的是开始的那个元素
        Connection conn = list.remove(0);
        
        //在把这个对象抛出去的时候, 对这个对象进行包装。
        Connection connection = new ConnectionWrap(conn, list);
        
        return connection;
    }
    
    /**
     * 用完之后,记得归还。
     * @param conn
     */
    public void addBack(Connection conn){
        list.add(conn);
    }
    
    //--------------下面还有没实现的方法--------------
}

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
    
    static String driverClass = null;
    static String url = null;
    static String name = null;
    static String password= null;
    
    static{
        try {
            //1. 创建一个属性配置对象
            Properties properties = new Properties();
            InputStream is = new FileInputStream("jdbc.properties");
            
            //使用类加载器,去读取src底下的资源文件。 后面在servlet
//          InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //导入输入流。
            properties.load(is);
            
            //读取属性
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            name = properties.getProperty("name");
            password = properties.getProperty("password");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取连接对象
     * @return
     */
    public static Connection getConn(){
        Connection conn = null;
        try {
            Class.forName(driverClass);
            //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver());
            //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
            //2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。
            conn = DriverManager.getConnection(url, name, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    
    /**
     * 释放资源
     * @param conn
     * @param st
     * @param rs
     */
    public static void release(Connection conn , Statement st , ResultSet rs){
        closeRs(rs);
        closeSt(st);
        closeConn(conn);
    }
    public static void release(Connection conn , Statement st){
        closeSt(st);
        closeConn(conn);
    }

    
    private static void closeRs(ResultSet rs){
        try {
            if(rs != null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            rs = null;
        }
    }
    
    private static void closeSt(Statement st){
        try {
            if(st != null){
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            st = null;
        }
    }
    
    private static void closeConn(Connection conn){
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            conn = null;
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读