用静态工厂方法代替构造器遇到多个构造器参数时要考虑用构建器

Posted 嘚吧嘚吧嘚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用静态工厂方法代替构造器遇到多个构造器参数时要考虑用构建器相关的知识,希望对你有一定的参考价值。

一、用静态工厂方法代替构造器

类通过共有的构造方法可以提供很大的优点:
1、构造方法可一有不同的名字,我们可以通过名字区分构造什么样子的对象,而构造器名字相同,当参数列表的数目相同 顺序不同时 很大的可能会用错构造方法。

2、可以每次调用他们的时候都使用相同的对象(单例模式),可以对一个对象重复的利用,而每次调用构造方法都会新建一个对象。当程序需要创建相同的对象或者创建对象的代价很高时,使用静态工厂是一个很好的选择。

3、使用静态工厂可以返回原返回类型的任意子类型。在静态工程方法中可以根据不同的条件返回不用的对象。

服务提供者框架:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从实现中解耦出来 减少服务提供者之间的关联。

4、使用泛型 创建参数化类型实例的时候 可以让代码更简洁。
编译器可以通过静态工厂来找到类型参数。

静态工厂方法

以Java中自带的Boolean类(基本类型boolean的包装类)为例,它的静态工厂方法为:

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

我们应该考虑用该方法替代构造器来获得一个Boolean的实例。

//使用构造器
Boolean b1 = new Boolean(true);
//使用静态工厂方法
Boolean b2 = Boolean.valueOf(true);

同样是传入一个true作为参数,两种方法有什么区别呢?

静态工厂方法的优点

优点1:它们有名称
假如我们想要提供多个具有相同签名的构造器,这在Java中是做不到的,除非把参数列表的顺序做些调整,但这会对用户很不友好。因此可以使用静态工厂方法,取不同的名字以表示不同的构造方式。

优点2:不必每次都创建新对象
适用于单例模式。

优点3:构成基于接口的框架
静态工厂方法返回对象所属的类可以是后来动态添加的。我们以服务提供者框架(Service Provider Framework)为例讲解,该框架的代表是JDBC API。

优点4:创建泛型类实例的代码更为简洁
请看下面两种创建泛型类实例的方式,后者比前者更为简洁。

//使用构造器创建
Map<String, List<String>> m1 = new HashMap<String, List<String>>();
//使用静态工厂方法创建
Map<String, List<String>> m2 = HashMap.newInstance();

前提是HashMap提供的静态工厂方法newInstance定义如下

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

这种情况下,编译器可以通过返回值类型推断K、V的具体类型。

静态工厂的缺点

类如果不含有共有的或者受保护的构造方法,就不能被子类化。
当使用静态工厂时,就是一个普通的static方法,在API文档中,构造方法有单独的区域,而静态方法不会被分割出来。

我们一定要考虑使用静态工厂!

 

 

 

二、遇到多个构造器参数时要考虑用构建器

当创建对象的时候需要大量的可选参数,那么静态工厂和构造器就不是好的选择。可以采用的方式:

1、重叠构造器:提供第一个只有必要参数的构造器,第二个构造器包含一个可变参数 然后两个可变参数一次类推 用this( )来调用 直到所有的可变参数都包含。
但是当有很多参数的时候,客户端代码会很难写 并且难阅读。

2、javaBeans模式 用setter 对属性进行赋值,来设置必要参数和可变参数 但是当构造过程被分到了几个调用中,在构造过程中javaBeans会出现不一致的状态,即多线程的情况。

3、一种好的模式(Builder模式)
不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成不可变的对象。
bulder可以是多个可变的参数。
对多个参数加约束条件时 可以用setter进行设置

构建器缺点:
1.构造器写起来很复杂
2.创建对象开销比较大
所以构建器模式只适用于需要传入很多种情况参数的时候,比如大于4种参数的配合,才比较划算。

以上是关于用静态工厂方法代替构造器遇到多个构造器参数时要考虑用构建器的主要内容,如果未能解决你的问题,请参考以下文章

第二条:遇到多个构造器参数时要考虑用构建器

读书笔记 - Effective Java01. 考虑用静态工厂方法代替构造器

Effective Java目录

第2条:遇到多个构造器参数时要考虑用构建器

Effective Java总结的78条

Java 《Effective Java 中文版 第2版》学习笔记 遇到多个构造器时要考虑用构建器