Effective Java(1)考虑静态工厂方法代替构造器

因为各种原因,好久没有来CSDN写博客了。今天决定为个人技术上的追求,也为能与他人分享,认认真真地写博客。

最近在读Effective Java,很经典的一本书。

Effective Java这本一共78条建议,分别从创建、销毁对象,Object原生的方法,类和接口,泛型,枚举和注释,方法,通用程序设计,异常,并发以及序列号11个方面,介绍了一些Java编程方面的一些建议和最佳实践。以前也读过,但是也就是那种拾起来,翻翻,然后扔掉的读法,太肤浅,不好。趁着这个机会一边读,一边好好整理下。

Effective Java(1)考虑静态工厂方法代替构造器

摘要:

在创建对象时,可以优先考虑使用静态工厂方法,因为相比使用构造器,静态工厂方法有4个优势:

  静态工厂方法的优点
1 可以用不同的方法名描述构造过程
2 可以在特定场景下复用已创建对象
3 可以返回原类型的任何子类
4 可以简化类型声明

但同时需注意静态工厂方法的2个劣势:

  静态工厂方法的缺点 注释
1 类无public或protected构造器时,子类化可能无法进行  
2 和普通静态方法无本质区别 可以通过命名规范来改善

可以使用命名规范避免无法区分静态方法和静态工厂方法:

  静态工厂方法的命名规范
1 valueOf - 类型转换
2 of - 类型转换
3 getInstance - 获取唯一实例
4 newInstantce - 创建新实例
5 getType - 获取唯一实例类型
6 newType - 创建新实例,返回类型

正文:

“考虑静态工厂方法代替构造器”是开篇第一条建议。这条建议的主要内容是,建议开发者在需要创建新对象时,优先考虑使用静态工厂方法代替构造器。

之所以这样建议,是因为静态工厂方法相比构造器而言,有4个优势,而同时又2个缺点。


一是每个静态工厂方法都可以有不同的名称。特别是创建一个相同的对象,而是用的参数不同时,恰当的有差异的方法名称让开发人员更容易区分。

比如User对象有2个属性:Long ID和String name。

public class User{
    Long id;
    String name;

    public User(Long id){
      this.id = id;
    }

    public User(String name){
      this.name = name;
    }   

   //Getters and Setters ...
}

如果使用构造器来创建对象,则针对不同的构造参数,需要调用不同的构造器方法:

public static void main(String args[]){
     User usrById = new User(1L);
     User usrByName = new User("myName");
}

这样随着构造器参数组合的增加,会导致客户端代码创建对象时难以阅读。而如果使用静态工厂方法则相对可以保证更清晰:

public static User newInstanceByName(Stirng name){ return new User(name):}

public static User newInstanceById(Stirng id){ return new User(id):}
...

public static void main(String args[]){
   User byName = User.newInstanceByName("myName");
   User byId = User.newInstanceById(1L);
}

静态工厂方法的第二个优势,就是 特定场景下不必每次都创建新的对象。比如Boolean.valueOf(boolean value)方法:  

public static Boolean valueOf(boolean b){ 
return b?Boolean.TRUE:Boolean.FALSE;}如果某对象在程序的生命周期中,只有有限种实例,那么使用静态工厂方法就可以设法复用这些实例,比如使用Flyweight模式。当然,实例的复用同时也需要考虑到一些其他的问题,比如线程安全。在评估上下文后,认为实例复用无害之后,静态工厂方法无疑可以更加高效的使用实例。

第三个优势,就是可以返回原对象的任何类型的子类型对象。这个特性可以让开发者针对已有的类实现轻松的实现基于接口的封装,但尽量少的减少代码改动。比如java.lang.Collections类,就使用了这样的技术,将非线程安全的集合类封装成为了线程安全的集合类。此外,静态工厂创建的对象甚至可以暂时不出现,知道需要时再编写,这就为Service Provider Framework提供了实现基础。这个等到第53条再详细说明。

第四个优势,就是可以简化类型声明:

Map<String, List<String>> m = new HahsMap<String, List<String>>();
可以使用静态工厂方法简化:

public static <K,V> HashMap<K,V> newInstance(){</span>
return new HashMap<K, V>();}Map<String, List<String>> m = HashMap.newInstance();
 这个是我没有想到的,神器般的方法。 
 


静态工厂方法也会有缺点,一是,如果类没有public或protected构造器,则类可能无法构造。另一个缺点是,静态工厂方法和其他的静态方法世纪上没有区别。对于第二个缺点,可以用一定的命名规范来现实:

valueOf / of- 类型转换

getInstance -返回唯一实例

newInstance - 返回不同实例

getType - 返回getInstance的对象类型

newType - 返回newInstance的对象类型




你可能感兴趣的:(java,阅读)