简单工厂模式适用于把业务类(比如方法,非实体类)的创建从程序员硬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();
    }
}

spring 使用工厂模式实现多态_类名