优势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之静态工厂代替构造器(一)相关推荐

  1. Effective Java(一)———— 代替构造器和Setter的构建器模式

    引言 Java语言中的一部经典著作<Effective Java>,里面涵盖了78条我们应该熟练的Java编程技巧. 本篇博客是该书学习的系列笔记第一篇.本系列博客不会与书中的78条建议完 ...

  2. Java 的静态工厂方法

    序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名字 2.2 第二个优势,不用每次被调用时都创建新对象 2.3 第三个优势,可以返回原返回类 ...

  3. 小鸡爪读Effective Java记录1:用静态工厂方法代替构造器

    //小鸡爪 == 菜鸡 遇到多个构造器参数时要考虑使用构建器 Preface 静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数.比如用一个类表示包装食品外面显示的营养成分标签.这 ...

  4. java 静态工厂方法代替构造器的好处

    Java 的静态工厂方法 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名字 2.2 第二个优势,不用每次被调用时都创建新对象 2.3 第 ...

  5. Effective Java 创建和销毁对象 2.遇到多个构造器参数时要考虑用构建器

    静态工厂跟构造器都有一个共同的局限性:不能很好的扩展到大量的参数. 例: package com.example.yancy.yancy; /**  * Created by yancy on 201 ...

  6. Effective Java读书笔记(二)

    Effective Java 读书笔记 (二) 创建和销毁对象 遇到多个构造器参数时要考虑使用构建器 创建和销毁对象 何时以及如何创建对象? 何时以及如何避免创建对象? 如何确保它们能够适时地销毁? ...

  7. Effective java 总结1 - 创建和销毁对象

    Effective java 总结 - 创建和销毁对象 第1条 用静态工厂方法代替构造器 优势 静态工厂方法有名称 不必每次调用的时候创建一个新的对象 可以返回原返回类型的任何子类型对象 返回对象的类 ...

  8. 《Effective Java》阅读笔记

    第2章 第1条:用静态工厂方法代替构造器 [1] 辅助理解静态工厂的文章,关于 Java 的静态工厂方法,看这一篇就够了! [2] 单例模式:Hi,我们再来聊一聊Java的单例吧 第2条:遇到多个构造 ...

  9. 《Effective Java》读书笔记

    引言 1 代码应该被重用 ,而不是被拷贝. 2 错误应该尽早被检测出来,最好是在编译时刻. 3 接口.类.数组是引用类型(对象), 基本类型不是 第二章 创建和销毁对象 1 考虑用静态工厂方法代替构造 ...

最新文章

  1. POJ1364基本的查分约束问题
  2. 软件版本具体代表什么意思
  3. adb可以连接linux设备吗,Linux通过ADB与Android设备交互
  4. android 初学者实现 popupwindow的自动弹出,Android popupWindow弹出窗体实现方法分析
  5. Weka开发[8]-ID3源码介绍
  6. tf.map_fn 多输入
  7. 5G对于数据中心的影响有哪些
  8. 算法笔记_面试题_14. strStr 长字符串中查找短字符串
  9. PHP处理数据为echarts多条折线图格式
  10. 最新可使用在线音乐网站+多解析源码
  11. MATLAB牛拉法计算潮流,Matlab牛拉法潮流计算程序
  12. 用计算机名共享打印机不能打印,共享打印机无法打印怎么办解决教程
  13. 批量创建文件夹-批处理(一)
  14. 计算机打字考试的技巧,快速打字有什么技巧
  15. lucas–kanade_Lucas–Kanade光流算法
  16. 海马玩模拟器启动失败,start machine failed! error code = 3和error code=21
  17. “TikTok+独立站”模式熟了?看Anker如何玩转社交私域流量导流独立站?
  18. 从ftp下载文件(word)到本地显示文件损坏或错误
  19. 成功解决tensorflow.python.framework.errors_impl.InvalidArgumentError报错问题
  20. Android 报错处理:All flavors must now belong to a named flavor dimension,Learn more at https://d.android

热门文章

  1. 交换网络中的嗅探和ARP欺骗
  2. 原来!我在4年前就开始体验雾游戏了!
  3. C++ 类型转换 :C语言的类型转换、C++的四种强制类型转换、explicit
  4. Redis的主从复制是如何做的?复制过程中也会产生各种问题
  5. e.printStackTrace() 会导致锁死?
  6. 分布式事务选型的取舍 | 建议收藏
  7. sync.Once 的前世今生
  8. LiveVideoStack Meet | 杭州:CV与流媒体将走向融合
  9. 【线上分享】视频质量评价:挑战与机遇
  10. 数据结构与算法之Manacher算法