Effective Java-第一章-Java的静态工厂方法

昨天读了一下 <Effective Java> 这本书的第三版, 把其中的第一章读完了,是写静态工厂方法的.

使用的OpenJDK9.0.0.15  这里写一个自己的一点理解

静态工厂方法代替构造方法

传统的获取一个对象的方法,是使用一个public的构造方法.现在我们有了另外一个技术,获取一个对象,一个类提供一个public static 工厂方法,返回一个类的实例.例如:

public static Boolean vlaueOf(boolean b){
return b?Boolean.TRUE:Boolean:FALSE;
}


一个类实例化可以提供静态工厂方法,也可以使用public的构造方法.他们都有各自的优缺点.


第一个优点:
它不像构造方法一样,他们有名字的.
我们能够给他起一个更直白的名字表达意思.
例如构造方法BigInteger(int,int,Random) 返回一个BigInteger ,当然了使用静态工厂方法更好的表达意思是BigInteger.probalePrime
当出现了多个构造方法的时候,根据构造方法的参数顺序来进行区分是一个坏主意,因为这种API记不住啊.
而工厂方法有名字,而且分别很大,使用工厂方法代替构造方法,可以选择更好的名字来区分

第二个好处:
他不像构造方法,他不需要每次调用的时候就创造一个新的对象.
他们允许不可变的类,使用提前已经构建的示例,或者还款的示例,当做当他们被创建了.避免重复创建多个不需要的对象.
例如:

public static Boolean vlaueOf(boolean b){
return b?Boolean.TRUE:Boolean:FALSE;
}


从来不创建对象.这就极大的改善了如果经常请求,尤其是创建的很消耗资源的时候.

还能够保证:单例,不可变的,


第三个好处:
他们能够返回任意类型,而不是构造方法只能返回自己的类型.

下面说的是以java的集合为例的多态,一个接口的多个不同的实现.所有的synchronize集合在不可实例的Collections类中都可以提供出来.如:静态方法 unmodifiableSet(Set<? extends T> s) 

java8的接口中可以有默认方法了.java8接口需要所有的成员都是public的
java9中允许有private static 方法,但是static 属性和static 成员类依然要是public的


第四个好处:
返回结果可以根据参数进行类型的转换,任何子类型都是有可能的.
EnumSet 类 没有public 构造方法,只有静态工厂方法.在openJDK中,他返回一个子类的实例.如果只有小于64个元素,返回的是RegularEnumSet 实例,是一个long.
当超过64个元素,工厂方法返回是JumboEnumSet 实例,返回的是一个long[] 数组.
这是两个实现,当然了,我们还可以为EnumSet提供第三种实现的方式.


第五个好处:
返回结果不需要存在,当工厂方法写的时候
像JDBC的链接

提供静态工厂方法的主要限制是类没有public 或者protected 的构造方法,不能对子类进行实例化

静态工厂方法另外一个缺点是程序员很难找到他们(因为以前实例化一个类,只需要知道是哪个就行了,现在我们却要知道他的工厂类.).
下面列举了一些常用的静态工厂的方法名字,距离详尽还差很远

一个方法名字示例:
from 一种类型转换方法.单个参数传入,返回一个符合要求的实例.例如:

Date d=Date.from(instant);


of   一个吧多个参数聚合然后返回一个实例的方法.例如:

Set<Rank>  facrCards = EnumSet.of(JACK,QUEEN,KING);


valueOf  一种作为from和of的替代.例如:

BigInteger prime=BigInteger.valueOf(Integer.MAX_VALUE);


instant 或者getInstance   返回一个参数描绘的实例,但不一定是同一个对象,例如:

StackWalker luke=StackWalker.getInstance(options);


create 或者 newInstance 像instance 或getInstance  方法保证每次被调用都返回一个新的对象.例如:

Object newArray =Array.newInstance(classObject,arrayLen);


getType 像getInstance 但是用在当一个工厂方法在一个不同的类中的时候,返回工厂方法,例如:

FileStore  fs=Files.getFileStore(path);


newType  像newInstance  但是用在如果工厂方法在一个不同的类中.返回工厂方法,例如:

BuffferedReader  br=Files.newBufferedReader(path);


type   一个简明的可以代替getType  和  newType,例如:

List<Complaint>  litany= Collection.list(legacyLitany);


独家总结:静态工厂方法和public 构造方法同时使用.他们都有相应的优点.
当然了更加的推荐使用工厂方法,可以避免通过反射来提供public构造方法.

我的理解其实就是为了把对象的创建,和使用分离开,因为我们使用对象作为一种封装数据的数据结构,我们只是把对象当做一种工具使用,真正关心的不是他的创建,而是在他的使用上面.这也是spring流行的原因,就是因为他帮助我们对整个项目中使用到的对象的进行管理,我们需要使用的时候直接进行注入就可以了.

说了这么多.其实也是我上面的写的我的理解. 理解是一回事,但是在实际中使用又是另外一回事了.你明天了也许会偷个懒什么的. 就直接new 了, 才懒得管什么工厂方法.毕竟有的时候业务都写不完.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值