Effective Java -- 用静态工厂方法来代替构造器
2017-10-28 10:36
573 查看
本文是 《Effective Java》的读书笔记,由于是Java进阶书,难免会有理解的偏差,发现有错误,非常欢迎能提出来,本人不胜感激!
为什么要考虑使用静态工厂方法代替构造器呢?本书中说明了以下的优点:
(1)静态工厂方法能提供一个可读性很高的名称来帮助你理解你要返回的对象是什么
利用书上的例子,在类型
这个构造函数很大概率返回的是一个素数(概率为(1−(2−100))
但是这个名字基本不能看出来他返回的可能为素数,于是利用静态工厂方法来表示,那就容易理解多了:
在前台我们写的代码的可读性是不是强多了:
(2)可以避免创建不必要的重复对象
如果我们需要经常的创建相同的对象,在创建对象的代价很高的时候,这个技术可以很好的去提升性能。
如下,我们看一下
这样就使得我们程序每次使用的都是我们我们预先创建好的实例,达到重复利用的效果。
在实现
fb3e
们就使用了静态工厂方法,如下:
[ 注 ]:以上只是最基本的单例,如需了解更多,欢迎访问:实现线程安全的Singleton
(3)可以返回原返回类型的任意子类型
在基于接口编程的框架中,如果我们不确定该接口要返回哪一种实例化的类(如果要根据相应的参数信息来判断),就可以使用静态工厂方法了。
举个简单的例子,如下代码
一个
然后再在 Map 类中写如下的静态工厂方法
上面的程序当然只是我的假想,当然你可以把这个思想用到自己构造的接口中去。
那么在Java有没有这样的用法呢?当然是有的,我们来看一下
在这个静态工厂方法中,就通过判断传入的底层枚举类型的大小(元素的个数),来选择返回的实例(如上代码注释)。
(4)在创建参数化实例的时候,可以使得代码更加的灵活
例如在创建一个
如果
然后在创建一个
当然,在更高的JDK版本中,可以直接使用下面的写法
套用一句以前常说的一句话:Every coin has two sides
那我们来看一下 静态工厂方法有哪些缺点吧
(1)一个类如果不含共有的或者受保护的构造器,就不能被子类化(即不能被其他的类继承)
(2)对于提供了静态工厂方法来实例化类的类,我们在查明相应方法的时候,会有一点点的困难。
在遵循一定的命名规范的时候,可以弥补这一缺点,如下的一些管用名称:
静态工厂方法和构造器各有用处,静态工厂通常更加合适,在实际编程中要多多考虑。
教学视频链接:Effective Java 之 用静态工厂方法来代替构造器
为什么要考虑使用静态工厂方法代替构造器呢?本书中说明了以下的优点:
(1)静态工厂方法能提供一个可读性很高的名称来帮助你理解你要返回的对象是什么
利用书上的例子,在类型
BigInteger中提供了一种构造函数:
public BigInteger(int bitLength, int certainty, Random rnd) { //…… }
这个构造函数很大概率返回的是一个素数(概率为(1−(2−100))
但是这个名字基本不能看出来他返回的可能为素数,于是利用静态工厂方法来表示,那就容易理解多了:
public static BigInteger probablePrime(int bitLength, Random rnd) { //…… }
在前台我们写的代码的可读性是不是强多了:
BigInteger bi1=BigInteger.probablePrime(4,new Random());
(2)可以避免创建不必要的重复对象
如果我们需要经常的创建相同的对象,在创建对象的代价很高的时候,这个技术可以很好的去提升性能。
如下,我们看一下
Boolean.valueOf(boolean)方法
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
这样就使得我们程序每次使用的都是我们我们预先创建好的实例,达到重复利用的效果。
在实现
Singleton的时候,我
fb3e
们就使用了静态工厂方法,如下:
class MySingleton{ private static MySingleton mySingleton=null; public static MySingleton newInstance(){ if(mySingleton==null){ MySingleton.mySingleton=new MySingleton(); } return mySingleton; } }
[ 注 ]:以上只是最基本的单例,如需了解更多,欢迎访问:实现线程安全的Singleton
(3)可以返回原返回类型的任意子类型
在基于接口编程的框架中,如果我们不确定该接口要返回哪一种实例化的类(如果要根据相应的参数信息来判断),就可以使用静态工厂方法了。
举个简单的例子,如下代码
Map<Object,Object> hashMapObj=new HashMap<Object, Object>(); Map<Object,Object> treeMapObj=new TreeMap<Object, Object>();
一个
Map接口可以实例化为
HashMap和
TreeMap等几种实例化类,如果我们需要根据传入的参数的信息判断该返回
HashMap还是
TreeMap,就可以写出如下代码:
Map<Object,Object> hashMapObj=Map.getInstance(Object obj);
然后再在 Map 类中写如下的静态工厂方法
public static<K,V> Map<K,V> getInstance(Object obj){ if(/*参数obj满足某某条件*/) { return new HashMap<K, V>(); } if(/*参数obj满足某某条件*/) { return new TreeMap<K, V>(); } /*……*/ /*等等等等*/ }
上面的程序当然只是我的假想,当然你可以把这个思想用到自己构造的接口中去。
那么在Java有没有这样的用法呢?当然是有的,我们来看一下
EnumSet中的
noneOf()方法,如下
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { Enum<?>[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) //如果长度小于64,则返回RegularEnumSet类型 return new RegularEnumSet<>(elementType, universe); else //反之,返回JumboEnumSet类型 return new JumboEnumSet<>(elementType, universe); }
在这个静态工厂方法中,就通过判断传入的底层枚举类型的大小(元素的个数),来选择返回的实例(如上代码注释)。
(4)在创建参数化实例的时候,可以使得代码更加的灵活
例如在创建一个
Map<K,V>实例的时候,经常会使用如下代码:
Map<Object, Object> hashMapObj = new HashMap<Object, Object>();
如果
Object类型又是一个复杂类型,这样循环,代码就会变得越来越冗长,如果
HashMap提供了如下静态的工厂方法,则就简化代码了。(事实上没有)
public static<K,V> HashMap<K,V> getInstance(){ return new HashMap<K,V>(); }
然后在创建一个
Map<K,V>实例的时候就可以使用下面简化的代码了:
Map<Object, Object> hashMapObj = HashMap.getInstance();
当然,在更高的JDK版本中,可以直接使用下面的写法
Map<Object, Object> hashMapObj = new HashMap();
套用一句以前常说的一句话:Every coin has two sides
那我们来看一下 静态工厂方法有哪些缺点吧
(1)一个类如果不含共有的或者受保护的构造器,就不能被子类化(即不能被其他的类继承)
(2)对于提供了静态工厂方法来实例化类的类,我们在查明相应方法的时候,会有一点点的困难。
在遵循一定的命名规范的时候,可以弥补这一缺点,如下的一些管用名称:
名称 | 实例 |
---|---|
valueOf | Boolean.valueOf() |
of | EnumSet.of() |
getInstance | Calendar.getInstance() |
newInstance | DocumentBuilderFactory.newInstance() |
getType | Character.getType() |
newType | 尚未邂逅…… |
教学视频链接:Effective Java 之 用静态工厂方法来代替构造器
相关文章推荐
- Effective Java —— 考虑用静态工厂方法代替构造器
- EffectiveJava-考虑用静态工厂方法代替构造器
- 【Effective Java笔记】第1条:考虑用静态工厂方法代替构造器
- Effective Java 中文版之学习 第1条:考虑用静态工厂方法代替构造器
- Effective Java 1:考虑使用静态工厂方法代替构造器
- Effective Java 学习笔记 使用静态工厂方法代替构造器
- Effective java第一条:考虑用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java中用静态工厂方法代替构造器的优缺点
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Java学习笔记1:考虑用静态工厂方法代替构造器
- Effective Java之静态工厂代替构造器(一)
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- Effective Java第一条:考虑用静态工厂方法替代构造器
- Java - 用静态工厂方法代替构造器
- 改善JAVA代码01:考虑静态工厂方法代替构造器
- Effective Java 3rd 条目1 考虑用静态工厂方法代替构造子
- 第一条:考虑用静态工厂方法代替构造器
- 考虑使用静态工厂方法代替构造器
- 【代码优化】考虑使用静态工厂方法代替构造器