Effective Java阅读笔记-item1
Dreamhead把他用大把银子买来的“Effective Java”借给我阅读,我真是很感动亚,我只能用行动来感谢Dreamhead了。^_^
1、使用静态工厂方法代替构造函数
静态工厂方法优点:
可命名性:(而构造函数的名字必须和类名一致),使class使用起来较容易,构造函数只是根据不同的函数signature来区分,对使用者来说容易发生调用错误。
内部cache特性:在静态工厂内部可采用cache等机制控制对象实例的产生,比如singleton机制。返回一个原类型的一个子类型的对象。(体现了面向接口,不知道我这么理解是否正确)
用我蹩脚的初学的java代码来说明问题吧^_^。
Consider the following code:
//BaseObj.java
public abstract class BaseObj{
public static BaseObj getInstance(String className){
try{
Class c = Class.forName(className);
return (BaseObj)c.newInstance();
}catch(Exception e){
return null;
}
}
public abstract void show();
};
//SubObj1.java
public class SubObj1 extends BaseObj{
public void show(){
System.out.println(" I am SubObj1");
}
};
//SubObj2.java
public class SubObj2 extends BaseObj{
public void show(){
System.out.println(" I am SubObj2");
}
};
//TestStaticFactoryMethod.java
public class TestStaticFactoryMethod{
public static void main(String[] args) {
BaseObj.getInstance("SubObj1").show();
BaseObj.getInstance("SubObj2").show();
}
}
//output:
I am SubObj1
I am SubObj2
从代码可以看出我们可以通过Reflection机制在runtime期间产生某种BaseObj的子类型,所以在编写BaseObj代码时我们根本不需要知道BaseObj到底有几个子类型。有的人说即使这样我们在使用的时候也要明确传入子类的类型的名字,也就是说还要指名道姓,如上面代码中我们传入"SubObj1"和"SubObj2",有人提出使用abstract factory的模式,显然有可能解决问题,但是就上面的论述"返回一个原类型的一个子类型的对象"而言,使用abstract factory显然是混淆了概念。这里可以用一些折中的办法,比如在BaseObj中维护一个map表,并利用配置文件来动态load sub class’s name and keys,这样我们只需修改配置文件就可以动态的增加子类型。
设计模式中的Factory pattern与这里谈到的工厂方法还是有一定区别的,不要混为一谈。首先我们这里谈的static factory method的产生对象是什么我们要搞清楚,是产生static factory method本身的对象或者其子类型的对象(上面的代码是产生子类型的对象)。而设计模式中的工厂模式中“工厂”和“产品”之间并无继承关系。
如设计模式工厂模式的一段例子代码:
public class Factory{
public static Sample creator(int which){
//getClass 产生Sample 一般可使用动态类装载装入类。
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
可以看出工厂的类型为:Factory ,而产品为SampleA or SampleB。
静态工厂方法缺点:
- 类如不提供public or protected就不能被子类化;
- 它和其它静态方法没有任何区别,在文档中不能显著体现出来它的作用
现在java标准包中很多都是在abstract class中提供static factory method的,abstract 类本身就是用来被继承的,所以说第一个缺点被淡化了,书的作者的观点是这个缺点鼓励程序员使用复合,少用继承。至于第二个缺点现在有两个被很多包使用的static factory method的名字,valueOf和getInstance。我们这么用就行了^_^。
从上面代码的分析中我们可以看到工厂方法有优点也有缺点,使不使用工厂方法你自己决定吧^_^。
评论