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

前言

对于类而言,为了让客户端获取它自身的一个实例,最传统的方法就是提供一个公有的构造器。还有一种方法,类可以提供一个公有的静态工厂方法,它只是一个返回类的实例的静态方法。

下面是一个来自Boolean的简单示例,这个方法将boolean基本类型值转换成了一个Boolean对象引用:

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

静态工厂方法相比构造器的优势

  • 它们有名称。
    如果构造器的参数本身没有确切地描述正被返回的对象,那么具有适当名称的静态工厂会更容易使用,产生的客户端代码也更易于阅读。
  • 不必再每次调用它们的时候都创建一个新对象。
    这使得不可变类可以使用预先构建好的实例,或者将构建好的实例缓存起来,进行重复利用,从而避免创建不必要的重复对象。
    静态工厂方法能够为重复的调用返回相同对象,这样有助于类总能严格控制在某个时刻那些实例应该存在。这种类被称作实例受控的类。编写实例受控的类有几个原因:
    • 使得类可以确保它是一个Singleton或者是不可实例化的。
    • 使得不可变的值类可以确保不会存在两个相等的实例,即当且仅当a==b时,a.equals(b)才为true,这是享元模式的基础。
  • 它们可以返回原返回类型的任何子类型的对象。
    这样我们在选择返回对象的类时就有了更大的灵活性。这种灵活性的一种应用是,API可以返回对象,同时又不会使对象的类变成公有的。以这种方式隐藏实现类会使API变得非常简洁。
  • 所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值。
    只要是已声明的返回类型的子类型,都是允许的。返回对象的类也可能随着发行版本的不同而不同。客户端永远不知道也不关心它们从工厂方法中得到的对象的类,它们只关心它是某个子类。
  • 方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在。
    这种灵活的静态工厂方法构成了服务提供者框架的基础,例如JDBC API。服务提供者框架是指这样一个系统:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把它们从多个实现中解耦出来。

静态工厂方法的缺点

  • 类如果不含公有的或者受保护的构造器,就不能被子类化。
  • 程序员很难发现它们。
    API文档中,它们没有像构造器那样在API文档中明确标识出来,因此,对于提供了静态工厂方法而不是构造器的类来说,要想查明如何实例化一个类是非常困难的。
    同时,通过在类或者接口注释中关注静态工厂,并遵守标准的命名习惯,也可以弥补这一劣势。

简而言之,静态工厂方法和构造器都各有用处,我们需要理解它们各自的长处。静态工厂经常更加适合,因此切忌第一反应就是提供公有的构造器,而不先考虑静态工厂。


 上一篇
遇到多个构造器参数时要考虑使用构建器 遇到多个构造器参数时要考虑使用构建器
前言静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。对于有很多可选参数的类,程序员一向习惯采用重叠构造器模式,在这种模式下,提供的第一个构造器只有必要的参数,第二个构造器有一个可选参数,第三个构造器有两个可选参数,以
2019-05-14
下一篇 
Spring Boot 使用 pagehelper 分页插件 Spring Boot 使用 pagehelper 分页插件
添加 pagehelper 依赖pom.xml 中添加: <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pageh
2019-05-08
  目录