一、静态工厂创建代替构造方法
1 优势
1.1 静态工厂方法可指定不同名字:见名知意
构造器构建对象时候,参数如果多,则构建时候不方便; 静态工厂可以根据名字,来区分得到的对象的具体的属性;
@Setter
@Getter
@ToString
@NoArgsConstructor
public class Student {
private String name;
private String address;
public Student ( String name) {
this . name = name;
}
public Student ( String name, String address) {
this . name = name;
this . address = address;
}
public static Student getStudentWithName ( String name) {
Student student = new Student ( ) ;
student. setName ( name) ;
return student;
}
public static Student getStudentWithNameAndAddress ( String name, String address) {
Student student = new Student ( ) ;
student. setName ( name) ;
student. setAddress ( address) ;
return student;
}
}
1.2 静态工厂方法能够创建单例
对于某些开销比较大的对象,同时只需要一个对象的类,不需要反复创建; 静态工厂方法可以只创建一个,但是构造方法构造会创建多个;
public class SecondDemo {
@Test
public void firstDemo ( ) {
for ( int i = 0 ; i < 10 ; i++ ) {
People instance = People. getInstance ( ) ;
System. out. println ( instance) ;
}
}
@Test
public void secondDemo ( ) {
for ( int i = 0 ; i< 10 ; i++ ) {
People instance = new People ( ) ;
System. out. println ( instance) ;
}
}
}
class People {
private static People people = new People ( ) ;
public People ( ) { }
public static People getInstance ( ) {
return people;
}
}
1.3 根据静态方法传入的不同参数,可以返回对应该方法的子类;
public class Test02 {
public static void main ( String[ ] args) {
Animal ani1 = Animal. getAnimal ( 12 ) ;
Animal ani2 = Animal. getAnimal ( 5 ) ;
System. out. println ( ani1. getClass ( ) ) ;
System. out. println ( ani2. getClass ( ) ) ;
}
}
@NoArgsConstructor
@Setter
class Animal {
private int weightKg;
public static Animal getAnimal ( int weightKg) {
if ( weightKg < 10 ) {
Cat cat = new Cat ( ) ;
cat. setWeightKg ( weightKg) ;
return cat;
} else {
Sheep sheep = new Sheep ( ) ;
sheep. setWeightKg ( weightKg) ;
return sheep;
}
}
}
class Cat extends Animal {
}
class Sheep extends Animal {
}
2. 劣势
2.1 子类继承遭破坏
若类中包含静态工厂方法,但构造器不是public或protected修饰,则不能被子类继承;破坏了类的继承性; 鼓励开发中尽可能使用复用,而不是继承;
2.2 类的文档难以阅读
类的API文档中,构造器比较容易发现,静态工厂方法难以发现,不利于他人知悉对象创建方式; 采用约定成俗的方法命名,如下为常见的命名;
Object valueOf( Object obj) ; Object of( Object obj) ;
public static Boolean valueOf( boolean b) {
return ( b ? TRUE : FALSE) ;
}
Object getInstance( params) ;
Object newInstance( parmas) ;
3. 总结
通常静态工厂方法更加实用,因此切忌一上来就使用构造方法;
二、多个构造方法考虑使用构建器
若一个类中包含的成员变量太多,一般使用多个构造方法; 每个构造方法都会存在: 参数多,构建对象时候参数容易混淆;
1. 优化一: JavaBean模式
采用无参构造创建对象,调用setter方法为对象赋值; javabean的模式存在着:不一致性的问题
2. 优化二: 构建器模式
public class ThirdDemo {
@Test
public void method ( ) {
Phone phone = new Phone. Builder ( "华为" , "红色" )
. price ( 2100D )
. weight ( 1D )
. size ( 5D )
. build ( ) ;
}
}
class Phone {
private String brand;
private String color;
private Double price;
private Double weight;
private Double size;
public static class Builder {
private String brand;
private String color;
private Double price;
private Double weight;
private Double size;
public Builder ( String brand, String color) {
this . brand = brand;
this . color = color;
}
public Builder price ( Double price) {
this . price = price;
return this ;
}
public Builder weight ( Double weight) {
this . weight = weight;
return this ;
}
public Builder size ( Double size) {
this . size = size;
return this ;
}
public Phone build ( ) {
return new Phone ( this ) ;
}
}
private Phone ( Builder builder) {
this . brand = builder. brand;
this . color = builder. color;
this . size = builder. size;
this . weight = builder. weight;
this . price = builder. size;
}
}
三、私有构造器或者枚举类强化单例模式
四、私有构造器强化不可实例化的对象
五、避免创建不必要的重复对象
六、消除过期对象的引用
七、避免使用终结方法