您的位置:首页 > Web前端

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

2017-12-12 12:34 155 查看
优势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注册进来就可以了,我可
4000
以利用静态工厂方法DriverManager.getConnection()返回你的Connection实现。

mysql服务商:好的,我注册好了,用户,你只需要调用

Class.forname(“com.mysql.jdbc.Driver”);我就帮你把我的driver注册进去,你可以直接通过DriverManager.getConnection()就能得到我实现的Conncetion了。

参考资料:Effective Java
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息