Effective Java之静态工厂代替构造器(一)
2017-12-12 12:34
155 查看
优势1:它们有名称,所以在多个构造器时,能够根据静态工厂的方法的名称找到哪个构造器。
优势2:能够实现单例模式,不必在每次调用重新创建新对象。
优势3:当创建参数化参数实例时,使用静态工厂方法更加简单。
优势4:它们可以返回原返回类型的任何子对象。
书中提到了展示这个优势的“服务提供者框架”,我们以jdbc为例,来看一下jdbc是如何利用静态工厂的。
看上去,短短两个api就能通过mysql服务商得到connection服务接口,我们看看具体是如何实现的:
过程:
Class.forName(“”)方法的作用是将这个class加载到虚拟机中,此时这个class执行了它的static代码块(而不是构造函数),从它的源代码中,我们可以看到,它调用了自己的构造器,并将其注册到DriverManager中;一个反射方法实际上干了很多事情。
connection=DriverManager.getConnection()方法从源代码看到,实际上就是遍历注册到它身上的driver,根据driver得到connection。
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
优势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
相关文章推荐
- EffectiveJava-考虑用静态工厂方法代替构造器
- Effective Java —— 考虑用静态工厂方法代替构造器
- Effective java第一条:考虑用静态工厂方法代替构造器
- 【Effective Java笔记】第1条:考虑用静态工厂方法代替构造器
- Effective Java -- 用静态工厂方法来代替构造器
- Effective Java 中文版之学习 第1条:考虑用静态工厂方法代替构造器
- Effective Java 学习笔记 使用静态工厂方法代替构造器
- Effective Java 1:考虑使用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java中用静态工厂方法代替构造器的优缺点
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java - 用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Effective Java 3rd 条目1 考虑用静态工厂方法代替构造子
- Effective Java第一条:考虑用静态工厂方法替代构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- Effective Java 之-----静态工厂与构造器
- 用静态工厂方法代替构造器
- 考虑使用静态工厂代替构造器