官方定义的好处:
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
个人理解:解耦!!!
下面利用反射机制自定义一个较为实用的工厂模式:
如果我们有老师,学生两种角色,他们都有说话的行为。很明显,可以定义父类或接口使之继承
package com.self.project;
/**
* 人类接口
* say():说话行为
* @author BreakingBad_
*
*/
public interface Person {
/**
* 说话方法
*/
public abstract void say();
}
具体实现的子类:
package com.self.project;
/**
* 学生
* @author BreakingBad_
*
*/
public class Student implements Person{
/**
* 学生说话的具体方法
*/
@Override
public void say() {
System.out.println("好的,老师");
}
}
package com.self.project;
/**
* 老师
*
* @author BreakingBad_
*
*/
public class Teacher implements Person {
/**
* 老师说话的具体方法
*/
@Override
public void say() {
System.out.println("同学们我们做游戏啦");
}
/**
* 老师报出数字
*/
public void sayNumbers(int[] numbers) {
System.out.println("同学们我报出的数是" +
numbers[1] + "\t" + numbers[2] + "\t" + numbers[3]);
}
}
之后,我们建立type.properties文件 存放参数名称key和映射的类地址
student=com.self.project.Student
teacher=com.self.project.Teacher
创建PropertiesReader工具,拿到properties文件内键值对,存入hashmap中
package com.self.project;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 工具类 读取Properties文件内容 将键值放入Map中
*
* @author BreakingBad_
*
*/
public class PropertiesReader {
// 储存properties文件中的key value的map
Map<String, String> personMap = new HashMap<String, String>();
/**
* 读取properties文件 存入personMap中
*
* @return
*/
public Map<String, String> getProperties() {
Properties properties = new Properties();
// 拿到输入流--->通过文件位置 web项目resource或src下就是classpath:***.properties
InputStream input = getClass().getResourceAsStream("type.properties");
try {// properties工具加载输入流
properties.load(input);
Enumeration<?> enumeration = properties.propertyNames();
while (enumeration.hasMoreElements()) {
// 读取properties文件
String key = (String) enumeration.nextElement();
String property = properties.getProperty(key);
personMap.put(key, property);
}
} catch (IOException e) {
e.printStackTrace();
}
return personMap;
}
}
拿到键值对后,创建工厂,工厂内用反射拿到类类型(类的CLASS对象)通过newInstance创建实例,面向接口编程不用细说了
package com.self.project;
import java.util.Map;
/**
* Person工厂
*
* @author BreakingBad_
*
*/
public class PersonFactory {
/**
* 根据传进来的Key返回具体Object
*
* @param key
* @return
*/
public static Person getInstance(String key) {
// 读取文件读取类传来的map<key,反射的类地址>
Map<String, String> personMap = new PropertiesReader().getProperties();
try {// 通过Class.forName.newInstance方法拿到类对象
Person person = (Person) Class.forName(personMap.get(key)).newInstance();
return person;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
测试:
package com.self.project;
/**
* 游戏开始
*
* @author BreakingBad_
*
*/
public class GamePlay {
public static void main(String[] args) {
Person teacher = PersonFactory.getInstance("teacher");//参数在properties文件中一定存在键值
teacher.say();
Person student = PersonFactory.getInstance("student");
student.say();
}
}
控制台输出: