十月读书笔记:Effective Java(一)--静态工厂方法及私有化构造函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l00149133/article/details/52777542

简述:
《Effective Java》是Joshua Bloch所著,Joshua是Sun公司的高级工程师,他也是我们所熟知的JAVA开发工具包中java.math和Java Collections Framework的开发者,所以在这本书中,大部分时候 Joshua是从一个平台开发者的角度(而非一个平台使用者)来考虑问题的

一. 静态工厂方法(statics factory method)
静态工厂方法是用来替代构造方法的。
通常我们要创建一个类的对象时,会使用类的构造方法:

public class Demo{
    public Demo(){...}
    ...
} 

静态工厂方法旨在代替构造方法,这样做可能会有如下几个好处:
1. 命名上,更加直观。通常静态工厂方法会用getInstance(比如单例模式)或者valueof(参考Integer,Boolean这些类)来命名,字面意思很清楚,而构造方法是没有名字的(这在你拥有多个构造方法时会有麻烦)。
2. 每次被调用时,不会一直创建新的对象。这样如果你要频繁的调用这个类的方法是,不需要一直创建新的对象,如下,每次我们调用getInstance,先检查instance是否为空:

public class Demo{
    private Demo instance;
    public Demo getInstance(){
        if(instance==null){
        instance = new Demo();
        }
        return instance;
   }
} 
  1. 构造方法只能返回类的实例,而静态工厂方法则可以返回类的子类的实例:
 //Demo是一个抽象类,不能直接创建它的实例
 public abstract class Demo{
 private static Map map = null;
 private static void initMapIfNeccury(){
 //这里,我们初始化了一个map,用来存储字符串和类的关系
 if(map == null){
     map = new HashMap();
 } 

 //省略的内容是从已经配置好的XML文件里读取数据,放到map中
 ...
 }

 public static Demo getInstace(String key){
 initMapIfNeccury();
 if(!map.containsKey(key)){
     return new DefaultDemo();
 }

 Class c = Class.forName(map.get(key).toString)
 if(c==null){
     //这里,DefaultDemo是Demo的一个子类
     return new DefaultDemo();
 }
 try{
     //可以明显看出待创建的对象具体创建哪个对象,在编译时并不知道,只有在运行时刻才知道,将对象的创建工作推迟到运行时,这即是优点,有是缺点,失去了编译检查的功能。
     //return返回的Demo实例,可以强转成你需要的子类类型
     //c.newInstance()是利用类的反射机制获取类实例
     return (Demo)c.newInstance();
 }catch(Exception exce){
     return new DefaultDemo();
 }
}

综上可以看出,静态工厂方法,其实包含了两个含义:静态(通过第2点可以体现)和工厂(通过第3点可以体现)

而笔者也指出了静态工厂方法的缺点:
1. 如果子类没有public的构造函数,就不能被子类化(针对上面的第三点的c.newInstance())。
2. 采用构造函数实例化对象,是语言的规范,而静态工厂方法与其他的静态方法没有区别,就增加了用户使用的区别。

PS:补充一个知识点,通常我们在工厂模式中,可以通过反射机制来创建一个类的实例:

//从xml配置文件中获得字符串
String className = readfromXMlConfig;
class c = Class.forName(className);
factory = (Demo)c.newInstance();

二. 通过私有化构造函数,强化类不可实例化的能力
我相信绝大多数java程序员都写过类似命名的类:NetworkUtil,FileManager,IOUtil……
在这些工具类中,我们所有的方法都是static方法,所以我们也无需实例化这些类。
笔者在这一节里指出,对于无需实例化的类,我们最好也私有化它的构造函数,以保证用户(应用开发程序员)不会实例化它,并避免用户对构造函数产生疑惑(其实对于工具类的开发者既是应用程序开发者来说,并不会如此,Joshua因为一直从事JAVA API的开发,才会对这种情况比较注意)。

PS:需要注意的是,如果类的构造函数私有化了,这个类是不能被继承的。
一个类不可被继承有两种方式:用final来修饰这个类,将类的构造函数私有化

猜你喜欢

转载自blog.csdn.net/l00149133/article/details/52777542