欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 反射与工厂设计模式

程序员文章站 2022-03-09 20:37:02
...

工厂设计曾经给过一个原则: 如果是你自己所编写的接口, 要想取得本接口的实例化对象, 最好使用工厂类来设计, 但是也需要知道传统工厂设计所带来的问题.

案例: 编写一个传统的工厂类

package com.cwq.beyond;

interface IFruit{
	public void eat();
}

class Apple implements IFruit{
	
	@Override
	public void eat() {
		System.out.println("[Apple]吃苹果.");
	}
}

class Factory{
	private Factory() {}
	public static IFruit getInstance(String className) {
		if ("apple".equals(className)) {
			return new Apple();
		}
		return null;
	}
}

public class TestDemo04 {
	public static void main(String[] args) throws Exception {
		IFruit fruit = Factory.getInstance("apple");
		fruit.eat();
	}
}

但是非常遗憾的是: 该工厂设计类在开发中根本就不可能使用, 因为在传统的工厂设计中, 当增加一个类的时候需要修改工厂类.
所以传统工厂类的最大弊端: 关键字 new

改进: 通过使用反射来完成处理对象的实例化

因为 Class 类可以使用 newInstance() 实例化对象, 同时 Class.forName() 能够接收 String 这个类名称.

package com.cwq.beyond;

interface IFruit {
	public void eat();
}

class Apple implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Apple]吃苹果.");
	}
}

class Cherry implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Cherry]吃樱桃.");
	}
}

class Orange implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Orange]吃橘子.");
	}
}

class Factory {
	private Factory() {
	}

	public static IFruit getInstance(String className) {
		IFruit fruit = null;
		try {
			fruit = (IFruit) Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return fruit;
	}
}

public class TestDemo04 {
	public static void main(String[] args) throws Exception {
		IFruit fruit = Factory.getInstance("com.cwq.beyond.Apple");
		IFruit fruit2 = Factory.getInstance("com.cwq.beyond.Orange");
		IFruit fruit3 = Factory.getInstance("com.cwq.beyond.Cherry");
		fruit.eat();
		fruit2.eat();
		fruit3.eat();
	}
}

所以现在可以发现, 通过反射类改进的工厂设计模式, 其最大的特征在于可以方便动态进行子类的扩充操作, 而关键字new 会造成耦合问题.
但是以上的程序依然存在缺陷 : 如果所 ,现在有 10W 个接口, 那么按照此类模式就意味着需要有 10W 个工厂, 而10W 个工厂完成的都是相同的功能, 这样就很浪费了, 所以使用泛型来解决此问题.

改进: 使用泛型解决优化

package com.cwq.beyond;

interface IMessage{
	public void print();
}

class MessageImpl implements IMessage{
	@Override
	public void print() {
		System.out.println("com.cwq.beyond");
	}
}


interface IFruit {
	public void eat();
}

class Apple implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Apple]吃苹果.");
	}
}

class Cherry implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Cherry]吃樱桃.");
	}
}

class Orange implements IFruit {

	@Override
	public void eat() {
		System.out.println("[Orange]吃橘子.");
	}
}

class Factory {
	private Factory() {
	}

	public static <T> T getInstance(String className) {
		T t = null;
		try {
			t = (T) Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}
}

public class TestDemo04 {
	public static void main(String[] args) throws Exception {
		IFruit fruit = Factory.getInstance("com.cwq.beyond.Apple");
		IFruit fruit2 = Factory.getInstance("com.cwq.beyond.Orange");
		IFruit fruit3 = Factory.getInstance("com.cwq.beyond.Cherry");
		fruit.eat();
		fruit2.eat();
		fruit3.eat();
		IMessage msg = Factory.getInstance("com.cwq.beyond.MessageImpl");
		msg.print();
	}
}

从实际的开发来讲, 工厂类上使用泛型之后, 就可以为更多的类和接口进行服务了, 这应该是之后实际开发中要使用的工厂方式.

总结:

在实际开发之中, 如果可以掌握这种泛型和反射的组合操作原则, 那么对于整体的代码你就可以编写出高可用的程序了.