反射与泛型对工厂模式的优化

1.反射的工厂模式

工厂模式的最大弊端是在工厂类中使用了new关键字,如果子类有n多个子类,则在工厂中需要写n个判断语句(详见工厂模式),这是很不理想的。因此我们可以用反射来优化工厂,利用newInstance()方法实例化对象,同时利用Class.forName()方法来接受String类的名称。
看例子:

interface Fruit{
	void eat();
}

class Apple implements Fruit{
	@Override
	public void eat() {
		System.out.println("eat apple!");
	}
}
/** 当有n个子类时也不需要在工厂内进行多次判断 */
class Factory{
	public static Fruit getInstance(String className) {
		Fruit fruit = null;
		try {
			fruit = (Fruit)Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return fruit;
	}
}

public class GenericFactoryTest {
	public static void main(String[] args) {
		Fruit fruit = Factory.getInstance("com.ajie.Apple");
		fruit.eat();
	}
}

此方法的最大优点是可以很方便的进行子类动态扩充,而工厂不需要跟着动态改变。
但是此方法同样有一个弊端,那就是当存在n个接口时,就需要定义n个工厂来与之对应,这样就大大的加大了代码的冗余,解决此问题就需要用泛型。


2.用泛型实现反射的工厂模式

利用泛型来实现工厂模式就是为了解决多个接口对应多个工厂的问题,看例子;

/** 定义n个接口*/
interface Fruit{
	void eat();
}
interface Person{
	void print();
}

class Factory{
	@SuppressWarnings("unchecked")
	public static T getInstance(String className) {
		T obj = null;
		try {
			// java9 obj = (T)Class.forName(className).getDeclaredConstructor().newInstance();
			obj = (T)Class.forName(className).newInstance();
		}catch(Exception e){
			e.printStackTrace();
		}
		return obj;
	}
}

class Apple implements Fruit{
	@Override
	public void eat() {
		System.out.println("eat apple!");
	}	
}

class Student implements Person{
	@Override
	public void print() {
		System.out.println("student print!");
	}	
}

public class PatternToReflectFactoryTest {
	public static void main(String[] args) {
    	Fruit f = Factory.getInstance("com.ajie.Apple");
    	f.eat();
    	Person p = Factory.getInstance("com.ajie.Student");
    	p.print();
   } 
}

结果是:

		eat apple!
		student print!

可以看到用泛型实现工厂可以使不同类型的、毫无关系的接口共用同一个工厂,这样就大大的提高了代码的简洁性,所以用泛型实现的反射类工厂是工厂模式在实际应用中的最终形态。
但是要注意的是在java9中newInstance()方法过时了,代替它的是getDeclaredConstructor().newInstance()方法。

你可能感兴趣的:(反射与泛型对工厂模式的优化)