静态工厂方法,也不知道为何叫这个名字。其实也就是一个静态函数,可以替代构造函数用。大名鼎鼎的 guava 就大量使用这种模式,这是非常有用的模式。

比如是

Integer i = Integer.valueOf(123);
Boolean bool = Boolean.valueOf(true);
//guava 的方法
ConcurrentMap<String,Integer> concurrentMap = Maps.newConcurrentMap();
ArrayList<Integer> array = Lists.newArrayList(1,2,3,4,5);

那么为什么要用静态工厂方法呢?

《effective java》解释得挺好的,下面我就进行“人类的本质”,并加点个人的见解。

静态工厂方法,可以不用创建新的对象

可以去看下 Integer.valueOf 函数

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

如果是 -128 到 127,通过 valueOf 构造对象能从对象池中直接获取,避免了对象重复构建!

如果是 Boolean 对象,只有 True 和 False 效果就更明显了。

有名字就是好

比如有个 User 类,有 Name,Address,Email等字段。有些数据只需 Name、和 Email 字段就可以了,有些字段只需 Name 和 Address 字段就可以了。但这确实不能创建两个相同类型的构造器!但你可以创建newNameWithEmail 或者 newNameWithAddress 的静态工厂函数。方便!

免去繁琐,不用写太多的通配符

这个也是被 guava 发扬广大,

比如:正常构造一个 HashMap

Map<String,List<String>> map = new HashMap<String,List<String>>();

前面类型都定义好了,为毛还要写 new HashMap<String,List<String>>();这样的一大串东西;

guava中只要这样就可以了,而且还是类型安全的!

Map<String,List<String>> map = Maps.newHashMap();

怎样做到的呢?看下以前版本的实现。

public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K,V>();
}

其实 ,java 官方也发现这个问题的 java 7 在这样一种语法糖

Map<String,List<String>> map = new HashMap<>();

java 9 后 有了 var 语法糖。可以写成

var map = new HashMap<String,List<String>>();

静态工厂函数的这个优势可有可无了

可以返回原返回类型的任何子类型

比如 EnumSet 根据 universe 数组的长度可以返回不同类型的 EnumSet

public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
implements Cloneable, java.io.Serializable { EnumSet(Class<E>elementType, Enum[] universe) {
} public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
}

确实是有点用,这种用法我是用得比较少。不喜欢用这样方式。觉得还不如不封装(逃

静态工厂方法的缺点

个人觉得,没啥缺点,甚至觉得每个类最好用静态工厂函数替代构造函数!最好还是把构造函数变成 private (逃。

这样可以强制不使用继承,只能用组合。

以上

java的设计模式 - 静态工厂方法的更多相关文章

  1. EFFECTIVE JAVA 第一天 静态工厂方法

    静态工厂方法:(这里指的是就是普通static方法),类可以通过静态工厂方法提供给它的客户端,而不是通过构造器.提供静态工厂方法而不是公有构造器,这样做有几大优势. 在类的实现中使用了API的类被称为 ...

  2. 高效JAVA之用静态工厂方法代替构造器

    程序员这行干的久了,总会染上一些恶习,我就染上一个让人深恶痛绝,自己却津津乐道的习惯,还不想改的那种,它可以叫做强迫症,也可以叫做洁癖.那就是我不允许我的IDEA出现一点点警告,什么黄色背景,绿色波浪 ...

  3. Java 的静态工厂方法

    本文转载自:https://www.jianshu.com/p/ceb5ec8f1174 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名 ...

  4. 比较 Java 静态工厂方法与构造函数

    1 什么是静态工厂方法 Java 静态工厂方法是在方法前加上 public static,让这个方法变为公开.静态的方法.该方法返回该类的一个实例,就好像一个工厂生产出一个产品.所以称之为静态工厂方法 ...

  5. 静态工厂方法和实例工厂方法及普通的bean

    容纳你的bean  bean工厂:最简单的容器,提供了基础的依赖注入支持.创建各种类型的Bean.  应用上下文(ApplicationContext):建立在bean工厂基础之上,提供系统架构服务. ...

  6. Spring学习--静态工厂方法、实例工厂方法创建 Bean

    通过调用静态工厂方法创建 bean: 调用静态工厂方法创建 bean 是将对象创建的过程封装到静态方法中 , 当客户端需要对象时 , 只需要简单地调用静态方法 , 而不需要关心创建对象的细节. 要声明 ...

  7. Java 设计模式之 简单工厂模式(静态工厂方法模式)

    简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的 ...

  8. Java设计模式———静态工厂

    上课时yqj2065要求:除了JDK等框架或工具中的类,自己编写的类不得使用new创建对象(Test除外). 据说是因为使用new会涉及到硬编码.(不是很懂) 所以要求用God类利用反射+配置文件来创 ...

  9. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. linux命令----查看磁盘空间

    今天用“web发布平台”发布测试的服务,两个节点中发现有一个节点没有发布成功,压测TPS始终上不去,排查后发现只有一个节点在打日志,另一个节点的服务进程都没有在运行,由此断定应该是没有发布成功,有点坑 ...

  2. 系统的讲解 - PHP 接口签名验证

    目录 概览 常用验证 单向散列加密 对称加密 非对称加密 密钥安全管理 接口调试工具 在线接口文档 扩展 小结 概览 工作中,我们时刻都会和接口打交道,有的是调取他人的接口,有的是为他人提供接口,在这 ...

  3. c# 基于文件系统实现的队列处理类

    现实业务中经常遇到需要队列处理的问题. 问题场景: 客户端记录设备运行数据,传输给服务器.在传输中可能存在延迟或中断情况.当中断时,系统传输数据可能因为无法传输或电脑重启,会导致服务器数据记录不连续. ...

  4. jdk源码阅读笔记-String

    本人自学java两年,有幸初入这个行业,所以功力尚浅,本着学习与交流的态度写一些学习随笔,什么错误的地方,热烈地希望园友们提出来,我们共同进步!这是我入园写的第一篇文章,写得可能会很乱. 一.什么是S ...

  5. 由ORACLE:ORA-28001: the password has expired(密码过期)引起ODI资料库连接失败

    今天,连接ODI,出现下面的错误 oracle.odi.core.config.WorkRepositoryResourceFailureException: ODI-10182: 资料档案库访问期间 ...

  6. HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP

    题图:by @Olga Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header)和实体组成.大多数 HT ...

  7. python中的del

    python中的del,只删除变量,不删除数据,具体表现为: a=1,c=a,del a,(c=1) 和 a = [1,2,3,4,5] b= a[0] del a[0] print a ([2,3, ...

  8. go.js remove 特定part

    我想删除一个实际上是背景的部分. 假设这是我添加part的方式 myDiagram.add( scope.gj(go.Part,//此Part未绑定到任何模型数据 { layerName:“Backg ...

  9. Web前端-Ajax基础技术(下)

    Web前端-Ajax基础技术(下) 你要明白ajax是什么,怎么使用? ajax,web程序是将信息放入公共的服务器,让所有网络用户可以通过浏览器进行访问. 浏览器发送请求,获取服务器的数据: 地址栏 ...

  10. 4.熟悉App Inventor 2编程界面

    以下图片来自 https://www.17coding.net/的 俄罗斯方块开发笔记 的 第二章 开发与测试环境 .感谢金老师的分享. 建议大家打开上面第二章的链接,认真阅读.