Effective Java之静态工厂代替构造器(一)

来源:互联网 发布:excel表格重复数据统计 编辑:程序博客网 时间:2024/04/29 01:40

优势1:它们有名称,所以在多个构造器时,能够根据静态工厂的方法的名称找到哪个构造器。

优势2:能够实现单例模式,不必在每次调用重新创建新对象。

优势3:当创建参数化参数实例时,使用静态工厂方法更加简单。

优势4:它们可以返回原返回类型的任何子对象。
书中提到了展示这个优势的“服务提供者框架”,我们以jdbc为例,来看一下jdbc是如何利用静态工厂的。

定义

多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。——–《Effective Java》

组件:

服务接口(Service Interface):提供者需要去实现的。提供者者注册API(provider Registration API):系统用来注册实现的。服务访问API(Service Access API):客户端用来获取实例的。服务提供者API(Service Provider Interface)(可选):创建其服务实例对象的。

使用方式:

Class.forname("com.mysql.jdbc.Driver");connection=DriverManager.getConnection("jdbc:mysql://localhost/Contacts?serverTimezone=UTC", "root", "Cc229654512");

看上去,短短两个api就能通过mysql服务商得到connection服务接口,我们看看具体是如何实现的:

实现

mysql的driver源代码:

package com.mysql.jdbc;import com.mysql.jdbc.NonRegisteringDriver;import java.sql.DriverManager;import java.sql.SQLException;public class Driver extends NonRegisteringDriver implements java.sql.Driver {    public Driver() throws SQLException {    }    static {        try {            DriverManager.registerDriver(new Driver());        } catch (SQLException var1) {            throw new RuntimeException("Can\'t register driver!");        }    }}

DriverManager源代码

 // List of registered JDBC drivers private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<DriverInfo>();    public static synchronized void registerDriver(java.sql.Driver driver)        throws SQLException {        if(driver != null) {            registeredDrivers.addIfAbsent(new DriverInfo(driver));        } else {            throw new NullPointerException();        }        println("registerDriver: " + driver);    }

java.sql.DriverManager.java( 这是getConnection方法中的片段)

 for(DriverInfo aDriver : registeredDrivers) {            // If the caller does not have permission to load the driver then            // skip it.            if(isDriverAllowed(aDriver.driver, callerCL)) {                try {                    println("    trying " + aDriver.driver.getClass().getName());                    Connection con = aDriver.driver.connect(url, info);                    if (con != null) {                        // Success!                        println("getConnection returning " + aDriver.driver.getClass().getName());                        return (con);                    }                } catch (SQLException ex) {                    if (reason == null) {                        reason = ex;                    }                }        }

过程:
Class.forName(“”)方法的作用是将这个class加载到虚拟机中,此时这个class执行了它的static代码块(而不是构造函数),从它的源代码中,我们可以看到,它调用了自己的构造器,并将其注册到DriverManager中;一个反射方法实际上干了很多事情。

connection=DriverManager.getConnection()方法从源代码看到,实际上就是遍历注册到它身上的driver,根据driver得到connection。

总结:

在jdbc中,
connection就是服务接口,也就是,得到它就得到了各种服务;
driver 服务提供者接口,也就是,得到它,它就能提供服务接口,这里就是connection。
DriverManager.getConnection()是服务访问API,也就是通过这个方法,能得到connection这个服务接口。
DriverManager.registerDriver()是提供者注册API

mysql或者是oracle服务商提供了connection的不同实现,通过自己的服务提供者接口(mysql的driver)注册到DriverManager中,我们可以看到DriverManager 并不是mysql或者是oracle服务商提供的类,而是java.sql提供的一个静态工厂,我们通过DriverManager.getConnection()方法得到服务商提供的Connection实现。

 
简单的,我们用一个对话理解:

sun公司:我把driverManager静态工厂完成了,服务商,你只要实现自己的Connection,实现自己的driver,然后用DriverManager.registerDriver()把你的driver注册进来就可以了,我可以利用静态工厂方法DriverManager.getConnection()返回你的Connection实现。

mysql服务商:好的,我注册好了,用户,你只需要调用
Class.forname(“com.mysql.jdbc.Driver”);我就帮你把我的driver注册进去,你可以直接通过DriverManager.getConnection()就能得到我实现的Conncetion了。

参考资料:Effective Java

阅读全文
1 0