本文章主要是对《Effective Java》对静态工厂方法的理解
第一次使用静态工厂方法是在HIT《Software Construction》课程的Lab2-P1的Graph.java中,对静态工厂方法的理解也相当有限,因此撰写此博客加深对静态工厂方法的理解。
Java 静态工厂方法在实际开发中经常使用,在《Effective Java》中第二章第一条即为:考虑使用静态工厂方法代替构造器。
静态工厂方法指的是在类中提供一个公有的静态方法,返回类的一个实例。
类的构造器名称被限制为类名,然而当构造器因不同的参数类型而无法确切的描述被返回的对象时,静态工厂方法却可以提供不同的函数名称作为不同构造方法。
例如如下代码:
public class Person {
private final SEX sex;
private final String name;
private final int age;
private Person(String name, int age, SEX sex){
this.sex = sex;
this.name = name;
this.age = age;
}
public static Person getManInstance(String name, int age){
return new Person(name, age, SEX.man);
}
public static Person getWomanInstance(String name, int age){
return new Person(name, age, SEX.woman);
}
}
enum SEX{
man,
woman;
}
在实际开发中,也如果是需要定义相同参数的构造器,可以通过交换参数位置的方法完成,但是这并不是一个好的方法,降低客户端代码的阅读性。
这种方法使得immutable的类可以使用预先构造好的实例或者是已经构造好的静态实例对象、进行重复利用。
这里提供以下immutable类的五条规则:
- 不提供任何mutator
- 保证类不会被扩展
- 所有的域都是final的
- 所有的域都是私有的
- 确保对于任何可变组件的互斥性访问
示例代码如下:
public class Position{
private final int x;
private final int y;
private static Position ORIGIN = new Position(0,0);
private Position(int x, int y){
this.x = x;
this.y = y;
}
public static Position getORIGIN(){
return ORIGIN;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
这样我们在选择返回对象的类时就有了更大的灵活性。
这种灵活性的一种应用是,API可以返回对象,同时又不会使对象的类变成公有的。以这种方式隐藏实现类会使API变得非常简洁。这项技术适用于基于接口的框架(interface-basedframework),因为在这种框架中,接口为静态工厂方法提供了自然返回类型。接口不能有静态方法,因此按照惯例,接口Type的静态工厂方法被放在一个名为Types的不可实例化的类(见第4条)中。
示例代码如下:
public class Person {
public static Person getStudent(){
return new Student();
}
}
class Student extends Person {
}//仅为一无内涵的示例
此优势主要体现在泛型初始化时,示例代码如下:
// 不使用静态工厂方法的情况:
Map map = new HashMap();
// HashMap中如果存在此方法:
public Map getInstance(){
return new HashMap();
}
// 即可简化成以下代码
Map map = HashMap.getInstance();
这一部分较有体会,例如以下代码(错误示例)
public class Person {
private final SEX sex;
private final String name;
private final int age;
private Person(String name, int age, SEX sex){
this.sex = sex;
this.name = name;
this.age = age;
}
public static Person getManInstance(String name, int age){
return new Person(name, age, SEX.man);
}
public static Person getWomanInstance(String name, int age){
return new Person(name, age, SEX.woman);
}
}
class Student extends Person {
}
实际在编译器的静态检查中会报错,原因是父类缺少公有的构造方法,而子类无法调用父类的私有构造器,导致子类无法生成构造器。
下面是一些静态工厂方法的惯用名称:
要不,点个赞?~