文章有参看其他博主博客:
- 考虑使用静态工厂方法替代构造方法[https://www.cnblogs.com/chenpi/p/5981084.html]
最近在阅读《Effectivce-java》的时候,里面提到了用静态工厂方法来给类创建对象,替代原有的构造方法。这里是说,并不是要取缔类中原有的构造器,而是说创建对象时不通过构造器,而是通过静态工厂方法来创建。这样做有它的有点,当然也有缺点,下面一起探究一下。
一、概述
在Java开发过程中,创建对象通常的做法是通过有参或者无参构造器创建对象。然而,你肯定遇到过这种情况:通常是一个某某实体类,有get,set方法,有多个带参构造器,只需保证参数顺序或者个数不同,很容易写出多个不同的带参构造器。然而,这样的做法导致的结果是该类的可读性过差,构造器冗余,如果没有方法注释说明,在调用构造器时还有可能调用错误的构造器,带来隐患BUG。
此时,静态工厂方法就显得很与众不同了。注意,静态工厂方法与【设计模式】中的工厂模式不同,并不是对应关系。此处的静态工厂方法仅仅也是一个普通的静态方法,只不过是我们赋予了它创造对象的意义。通过概念我们可以区分:
-
静态工厂方法通常指的是某个类里的静态方法,通过调用该静态方法可以得到属于该类的一个实例
-
工厂方法模式是一种设计模式,指的是让具体的工厂对象负责生产具体的产品对象,这里涉及多种工厂(类),多种对象(类),如内存工厂生产内存对象,CPU工厂生产CPU对象
-
静态工厂方法跟简单工厂模式倒有那么点像,不过区别也挺大,简单工厂模式里的静态工厂方法会创建各种不同的对象(不同类的实例),而静态工厂方法一般只创建属于该类的一个实例(包括子类)
二、使用静态工厂方法的优势
1.可读性强
没错,静态工厂方法可以起不同的方法名称,可读性强。而构造方法非常不幸的是,它必须和类名保持一致,导致阅读性差,甚至会在代码中调用错误的构造方法。
示例:
假设我们需要写一个产生随即数的类RandomIntGenerator,该类有两个成员属性:最小值min和最大值max,我们的需求是需要创建三种类型的RandomIntGenerator
对象:
1、大于min,小于max;
2、大于min 小于Integer.MAX_VALUE;
3、大于Integer.MIN_VALUE 小于max
如果使用传统方法去设计:
public class RandomIntGenerator
{
/**
* 最小值
*/
private int min = Integer.MIN_VALUE;
/**
* 最大值
*/
private int max = Integer.MAX_VALUE;
/**
* 大于min 小于max
* @param min
* @param max
*/
public RandomIntGenerator(int min, int max)
{
this.min = min;
this.max = max;
}
/**
* 大于min 小于Integer.MAX_VALUE
*/
public RandomIntGenerator(int min)
{
this.min = min;
}
// 报错:Duplicate method RandomIntGenerator(int) in type RandomIntGenerator
// /**
// * 大于Integer.MIN_VALUE 小于max
// */
// public RandomIntGenerator(int max)
// {
// this.max = max;
// }
}
观察以上代码,我们发现,以上代码不仅可读性差(new RandomIntGenerator(1, 10)与new RandomIntGenerator(10),不查文档,不看注释很难知道其创建的对象的具体含义),而且在设计最后一个构造方法的时候,还报错,因为已经存在一个参数一致的工作方法了,提示重复定义;
那么假设我们使用静态工厂方法会怎样呢,如下所示:
public class RandomIntGenerator
{
/**
* 最小值
*/
private int min = Integer.MIN_VALUE;
/**
* 最大值
*/
private int max = Integer.MAX_VALUE;
/**
* 大于min 小于max
* @param min
* @param max
*/
public RandomIntGenerator(int min, int max)
{
this.min = min;
this.max = max;
}
/**
* 大于min 小于max
* @param min
* @param max
*/
public static RandomIntGenerator between(int min, int max)
{
return new RandomIntGenerator(min, max);
}
/**
* 大于min 小于Integer.MAX_VALUE
*/
public static RandomIntGenerator biggerThan(int min)
{
return new RandomIntGenerator(min, Integer