Effective Java之静态工厂代替构造器(一)
优势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 driversprivate 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
Effective Java之静态工厂代替构造器(一)相关推荐
- Effective Java(一)———— 代替构造器和Setter的构建器模式
引言 Java语言中的一部经典著作<Effective Java>,里面涵盖了78条我们应该熟练的Java编程技巧. 本篇博客是该书学习的系列笔记第一篇.本系列博客不会与书中的78条建议完 ...
- Java 的静态工厂方法
序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名字 2.2 第二个优势,不用每次被调用时都创建新对象 2.3 第三个优势,可以返回原返回类 ...
- 小鸡爪读Effective Java记录1:用静态工厂方法代替构造器
//小鸡爪 == 菜鸡 遇到多个构造器参数时要考虑使用构建器 Preface 静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数.比如用一个类表示包装食品外面显示的营养成分标签.这 ...
- java 静态工厂方法代替构造器的好处
Java 的静态工厂方法 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名字 2.2 第二个优势,不用每次被调用时都创建新对象 2.3 第 ...
- Effective Java 创建和销毁对象 2.遇到多个构造器参数时要考虑用构建器
静态工厂跟构造器都有一个共同的局限性:不能很好的扩展到大量的参数. 例: package com.example.yancy.yancy; /** * Created by yancy on 201 ...
- Effective Java读书笔记(二)
Effective Java 读书笔记 (二) 创建和销毁对象 遇到多个构造器参数时要考虑使用构建器 创建和销毁对象 何时以及如何创建对象? 何时以及如何避免创建对象? 如何确保它们能够适时地销毁? ...
- Effective java 总结1 - 创建和销毁对象
Effective java 总结 - 创建和销毁对象 第1条 用静态工厂方法代替构造器 优势 静态工厂方法有名称 不必每次调用的时候创建一个新的对象 可以返回原返回类型的任何子类型对象 返回对象的类 ...
- 《Effective Java》阅读笔记
第2章 第1条:用静态工厂方法代替构造器 [1] 辅助理解静态工厂的文章,关于 Java 的静态工厂方法,看这一篇就够了! [2] 单例模式:Hi,我们再来聊一聊Java的单例吧 第2条:遇到多个构造 ...
- 《Effective Java》读书笔记
引言 1 代码应该被重用 ,而不是被拷贝. 2 错误应该尽早被检测出来,最好是在编译时刻. 3 接口.类.数组是引用类型(对象), 基本类型不是 第二章 创建和销毁对象 1 考虑用静态工厂方法代替构造 ...
最新文章
- POJ1364基本的查分约束问题
- 软件版本具体代表什么意思
- adb可以连接linux设备吗,Linux通过ADB与Android设备交互
- android 初学者实现 popupwindow的自动弹出,Android popupWindow弹出窗体实现方法分析
- Weka开发[8]-ID3源码介绍
- tf.map_fn 多输入
- 5G对于数据中心的影响有哪些
- 算法笔记_面试题_14. strStr 长字符串中查找短字符串
- PHP处理数据为echarts多条折线图格式
- 最新可使用在线音乐网站+多解析源码
- MATLAB牛拉法计算潮流,Matlab牛拉法潮流计算程序
- 用计算机名共享打印机不能打印,共享打印机无法打印怎么办解决教程
- 批量创建文件夹-批处理(一)
- 计算机打字考试的技巧,快速打字有什么技巧
- lucas–kanade_Lucas–Kanade光流算法
- 海马玩模拟器启动失败,start machine failed! error code = 3和error code=21
- “TikTok+独立站”模式熟了?看Anker如何玩转社交私域流量导流独立站?
- 从ftp下载文件(word)到本地显示文件损坏或错误
- 成功解决tensorflow.python.framework.errors_impl.InvalidArgumentError报错问题
- Android 报错处理:All flavors must now belong to a named flavor dimension,Learn more at https://d.android