这学期的任务做的差不多了,空出点时间,鉴于好长时间没有编程了,于是翻出《Effective Java》重读,顺便实现点里头的内容加深理解。恩,好书~~
第一条:考虑用静态工厂方法代替构造函数
好处:
1. 静态工厂方法有名字,更易于理解而且不易用错。
2. 每次被调用的时候不是非得创建一个新对象,而且可以根据需要创建指定数量的对象。(比如singleton)
3. 与构造函数不同,它们可以返回一个原返回类型的子类。同时,返回的类型在编写工厂方法的时候不一定真的存在
下面是书上例子的实现,可以看到MyRectangle类可以通过在编写完静态工厂方法之后再动态配置的方法添加,配置文件名为class.properties,字符串和类型名称的映射。
//Shape.java 基类
package Note01;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Shape {
public void whoAmI() {
System.out.println("I am Shape.");
}
private static Map implementations = null;
//初始化类的映射表
private static synchronized void initMapIfNecessary() {
if (implementations == null) {
implementations = new HashMap();
}
try {
//加载配置文件
String path = System.getProperty("user.dir");
File file = new File(path + "/Note01/class.properties");
InputStream propFile = new FileInputStream(file);
Properties properties = new Properties();
properties.load(propFile);
Set keys = properties.keySet();
//好像这种写法是5.0之后才支持的吧
for(Object key : keys) {
String strKey = (String)key;
String className = properties.getProperty(strKey);
Class c = Class.forName("Note01." + className);
implementations.put(key, c);
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//由名字获得类型
public static Shape getInstance(String key) {
initMapIfNecessary();
Class c = (Class)implementations.get(key);
if (c == null) {
return new Shape();
}
try {
return (Shape)c.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
return new Shape();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
return new Shape();
}
}
}
//MyCircle.java
package Note01;
public class MyCircle extends Shape {
public MyCircle() {
super();
}
public void whoAmI() {
System.out.println("I am Circle.");
}
}
//MyTriangle.java
package Note01;
public class MyTriangle extends Shape {
public MyTriangle() {
super();
}
public void whoAmI() {
System.out.println("I am triangle.");
}
}
//最初的class.properties文件,没有MyRectangle类的描述
circle=
MyCircle
triangle=
MyTriangle
//Test.java
package Note01;
public class Test {
public static void main(String[] args) {
Shape.getInstance("circle").whoAmI();
Shape.getInstance("triangle").whoAmI();
Shape.getInstance("rectangle").whoAmI();
}
}
运行Test.java结果为:
I am Circle.
I am triangle.
I am Shape.
在
class.properties
中增加
rectangle=
MyRectangle
再次运行
Test.java
结果为:
I am Circle.
I am triangle.
I am rectangle.