简单工厂模式适用于把业务类(比如方法,非实体类)的创建从程序员硬new出来到反转给程序本身控制调用。来实现解耦,实现仅一次读取配置文件,反复调用。
在resources下创建配置文件application.properties
userService=com.withub.service.impl.UserServiceHttpImpl
productService=com.withub.service.impl.ProductServiceImpl
分别创建接口类、实现类
package com.withub.service;
public interface UserService {
public boolean login();
}
package com.withub.service;
public interface ProductService {
public void getProduct();
}
package com.withub.service.impl;
import com.withub.service.UserService;
public class UserServiceImpl implements UserService {
public boolean login() {
System.out.println("UserServiceImpl...");
return false;
}
}
package com.withub.service.impl;
import com.withub.service.ProductService;
public class ProductServiceImpl implements ProductService {
public void getProduct() {
System.out.println("ProductServiceImpl...");
}
}
在pom.xml添加测试依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.withub</groupId>
<artifactId>spring-demo-01</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
接下来是重点了,我们新建工厂类ApplicationContext ,代码中会有详细的注释
package com.withub.factory;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class ApplicationContext {
private static String config = "/application.properties"; //设置默认的配置路径
public ApplicationContext() {} //使用无参构造函数就是使用默认的配置地址
public ApplicationContext(String path) {config = path;} //把路径传过来
private static Map<String, Object> context = new HashMap<String, Object>(); //模拟容器,使用HashMap键值对来存储String 对象类名、Object对象类,
static { //读配置文件,静态代码块可以在类加载时第一个运行并只运行一次,后续可以反复调用其输出
Properties properties = new Properties(); //申明String类型 属性集,每个键都对应一个值
try {
InputStream inputStream = ApplicationContext.class.getResourceAsStream(config); //读取配置文件并放入输入流
properties.load(inputStream); //输入流加载进属性集
for (Object key : properties.keySet()
) {
Object obj = create(properties.getProperty(key.toString())); //调用下面的create方法来遍历输出每个key对应的Object对象
context.put(key.toString(), obj); //往map填充数据,实现整个ApplicationContext方法调用过程中,可以随时通过key对象类名找到对象类Object
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static Object create(String className) { //反射出对象类,就是通过包名、类名的相对位置找到对象类,以便调用其方法、属性,这里的私有权限,是包装起来,因为这里属于静态代码块的调用方法,一次性创建好所有的对象类,反复调用,所以无需公开
Object obj = null;
try { //创建过程如果产生异常可以报错
Class clazz = Class.forName(className); //实现反射的具体方法,通过包名、类名的相对位置找到对象类,以便调用其方法、属性
obj = clazz.newInstance(); //调用被反射对象类的无参构造方法来创建出对象类
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
public Object getBean(String id) { //公开调用方法,需要就直接有这个方法
return context.get(id); //返回key:id 对象类名 的 值value 对象类
}
}
最后就是测试方法以及输出结果了,实现根据配置文件来自动对应的实现类方法,实现根据类名轻松调用实现类的方法而避免反复修改主程序。
import com.withub.factory.ApplicationContext;
import com.withub.factory.BeanFactory;
import com.withub.service.ProductService;
import com.withub.service.UserService;
import org.junit.Test;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactoryTest {
@Test
public void applicationContextTest() {
ApplicationContext context = new ApplicationContext();
// UserService userService = (UserService) context.getBean("userService");
// userService.login();
ProductService productService = (ProductService) context.getBean("productService");
productService.getProduct();
}
}