工厂模式+反射+properties,为了不要一直去new,就把new的工作交给特定一个类去创建,拿下面的例子来说,但是又有一个新问题,就是如果有100种动物,那么需要100个动物工厂,于是乎加入了反射和properties,具体实现如下:
1、Animal类:
public class Animal {
private String name;
private Integer age;
private String type;
int aa;
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
", type='" + type + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Animal() {
}
public Animal(String name, Integer age, String type) {
this.name = name;
this.age = age;
this.type = type;
}
private Animal(String name, String type) {
this.name = name;
this.type = type;
}
private Animal(String name,int num) {
this.name = name;
}
}
2、Cat类:
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, Integer age, String type) {
super(name, age, type);
}
}
3、Dog类:
public class Dog extends Animal{
public Dog() {
}
public Dog(String name, Integer age, String type) {
super(name, age, type);
}
}
4、AnimalFactory类:
public class AnimalFactory {
/**
* 动物工厂总接口
*/
//1. 生产动物
//2. 加入参数 : 传递过来一个 需求动物的 全类名!
Animal createAnimal(String key) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
String path = getPath(key);
Class> aClass = Class.forName(path);
Constructor> declaredConstructor = aClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Object o = declaredConstructor.newInstance();
return (Animal) o;
}
//读取配置文件
public static String getPath(String key) throws IOException {
//1. 创建出配置文件对象
Properties p = new Properties();
//2. 加载配置文件
p.load(new FileInputStream("animalPath.properties"));
//3.根据KEY获取VALUE
String path = p.get(key).toString();
return path;
}
}
5、Test类:
public class Test {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {
// 硬编码问题 ---- 常量字符串 经常改动的字符串 , 不应该写在代码中
// 原因: 如果更改这些字符串或者 常量 , 那么会造成整个框架中所有的类都要重新编译一遍!!!
AnimalFactory af = new AnimalFactory();
Scanner input = new Scanner(System.in);
System.out.println("请输入您要创建的动物:");
String key = input.next();
Animal animal = af.createAnimal(key);
System.out.println(animal);
}
}
6、animalPath.properties文件:
cat=com.puppet.test02.Cat
dog=com.puppet.test02.Dog
7、总结:
工厂 + 反射 + 配置文件 + 泛型的模式下: 配置文件是工具、工厂、用户之间的纽带: 配置文件存放工具具体类的全类名以及类标识; 用户调用工厂生产工具时,需要生产那种工具,就将该工具类在配置文件中的类标识传递给工厂就可以生产对应工具了; 工厂根据用户传递过来的类标识,从配置文件中获取具体类全类名,利用反射完成对应工具的生产; 在这种情况下: 工厂与工厂生产的产品在编译时是没有关联的,只有在运行时根据实际需要工厂生产具体的产品,解耦很明显; 泛型作用: 泛型扩大了工厂的生产能力,原理工厂只能生产工具类产品,使用泛型后,工厂就是一个全能工厂了,可以生产包括工具在类的所有产品; 只要有对应的产品类,并且在配置文件中完成产品类配置,工厂就可以生产这种产品;