Effective Java:用静态工厂方法代替构造器

1 静态工厂方法与构造器

构造器就是类的构造方法,名称与类名相同,只是方法参数不一样;

静态工厂方法就是一个返回类的实例的静态方法,例如Boolean类中的valueOf方法:

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

2 静态工厂方法的优势

2.1 优势一:工厂方法名可以自定义,可以定义为有语义的名称

例如,BigInteger类中,构造器BigInteger(int, int, Random)可能返回一个素数,但是对于调用者来说不清晰;如果用名为BigInteger.probablePrime静态工厂方法来表示,显得更清楚。

再举一个JDK的例子:Executors类,在这个类中有newFixedThread、newSingleThreadExecutor、newCachedThreadPool等静态方法,因为它们有“名字”,所有就较为清晰的明白API的含义。

2.2 优势二:不必在每次调用的时候都创建一个新对象

public class Instance() {
    private static Instance instance = new Instance();
    private Instance(){}
    public static Instance getInstance() {
    return instance;
    }
}

2.3 优势三:可以返回原返回类型的任何子类型的对象

举个JDK中的例子:Collections类

List list = Collections.synchronizedList(new ArrayList())

这个例子就说明了可以返回原返回类型的任何子类型的对象。

2.4 优势四:所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值

结合优势三,意思就是,可以返回不同的子类对象,这些子类对象对客户端来说是不可见的,因此可以灵活地按需返回不同的子类对象。

2.5 优势五:方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在

TODO

3 静态工厂方法的缺点

3.1 缺点一:类如果不含公有的或者受保护的构造器,就不能被子类化

例如,要想将Collection Framework中的任何便利的实现类子类化,这是不可能的。但是这样也许会因祸得福,因为它鼓励程序员使用复合(composition),而不是继承,这正是不可变类型所需要的。

3.2 缺点二:查找API比较麻烦

在API文档中,静态工厂方法没有像构造器那样在API文档中明确标识出来,因此,对于提供了静态工厂方法而不是构造器的类来说,要想查明如何实例化一个类是非常困难的。

静态工厂方法的一些惯用名称:

3.2.1 from——类型转换方法

只有单个参数,返回该类型的一个相对应的实例,例如

Date d = Date.from(instant);

3.2.2 of——聚合方法

带有多个参数,返回该类型的一个实例,把它们合并起来,例如

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

3.2.3 valueOf——比from和of更繁琐的一种替代方法

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

3.2.4 instance或者getInstance

返回的实例时通过方法的(如有)参数来描述的,但是不能说与参数具有同样的值,例如

StackWalker luke = StackWalker.getInstance(options);

3.2.5 create或者newInstance

像instance或者getInstance一样,区别在于每次调用都返回一个新的实例,例如:

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

3.2.6 getType

像getInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型,例如:

FileStore fs = Files.getFileStore(path);

3.2.7 newType

像newInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型,例如:

BufferedReader br = Files.newBufferedReader(path);

3.2.8 Type

getType和newType的简版,例如

List<Complaint> litany = Collections.list(LegacyLitany);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值