在分析工厂模式之前,我们先看看普通模式下的Java三层结构。
Controller(表现层)-Service(业务层)-Dao(持久层、数据库连接层),基于此三层结构完成JavaWeb相关业务。
假设我们要完成的业务是添加员工信息,
先创建Dao包,创建EmpDao接口和EmpDaoFactory实现类。Dao包结构.pngpackage com.yd.dao;
/**
* 员工模块Dao(持久层)接口
*
*/
public interface EmpDao {
// 添加员工信息
public void addEmp();
}package com.yd.dao;
/**
* 员工模块Dao(持久层)接口实现类
*
*/
public class EmpDaoImpl implements EmpDao{
public void addEmp() {
System.out.println("Dao层的addEmp()方法执行了..");
}
}
再创建Service包,创建EmpService接口和EmpServiceImpl实现类,在实现类中创建Dao接口的子类对象,这样做是程序之间的耦合性上升。
package com.yd.service;
/**
* 员工模块的service(业务层)接口
*
*/
public interface EmpService {
// 添加员工信息
public void addEmp();
}package com.yd.service;
import com.yd.dao.EmpDao;
import com.yd.dao.EmpDaoImpl;
/**
* 员工模块的service(业务层)接口实现类
*
*/
public class EmpServiceImpl implements EmpService{
//调用Dao接口的子类对象
//new对象使程序之间的耦合性上升
private EmpDao dao=new EmpDaoImpl();
public void addEmp() {
System.out.println("调用dao层的方法添加员工信息");
}
}
最后创建controller包,在包中创建EmpController类package com.yd.controller;
import org.junit.Test;
import com.yd.service.EmpService;
import com.yd.service.EmpServiceImpl;
/**
* 模拟表现层
* controller-> service-> dao
*
*/
public class EmpController {
/**
* 获取service接口的子类实例
* new对象造成程序耦合性上升
*/
//EmpService成员变量手动属性注入,属性注入了一个EmpServiceImpl对象。
private EmpService service=new EmpServiceImpl();
@Test
public void testAddEmp() {
System.out.println("调用service层的方法添加员工信息");
service.addEmp();
}
}
我们可以发现,在EmpServiceImpl类中创建了EmpDaoImp类的对象,两个类之间的耦合性上升;在EmpController类中创建了EmpSericeImpl对象,两个类之间的耦合性上升。
直接new对象使程序的耦合性上升,为日后的维护升级带来麻烦。
工厂方式解耦,完美解决了模块之间的耦合性过高的问题。
工厂模式,顾名思义,就是建立一个对象工厂,利用工厂来创建每个实现类的对象。就像工厂生产手机、电脑等工业品一样,这个工厂什么对象都能造!
在改造以上代码之前,先了解一些概念。
bean:可重用组件
JavaBean:java语言编写的可重用组件,例如service层,dao层,Controller层。
bean分为业务bean和实体bean。
业务bean:处理业务逻辑,service层和Dao层
实体bean:封装数据,相当于mvc设计模式的model、POJO,自己编写的Emp实体类。
如何解耦?提供配置文件,在配置文件中配置service和dao的实现类
通过工厂读取配置文件中的全限定类名,利用反射创建对象,如.properties和.xml文件
改造上面的代码,第一步:创建一个Factory包和BeanFatory类。
package com.yd.Factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
//声明一个Properties对象,在静态代码块中初始化
private static Properties prop;
static {
//prop实例化
prop = new Properties();
//获取配置流对象,得到配置文件的内容
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("config.properties");
try {
//将配置文件中的内容读到Prop对象中
prop.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("初始化properties对象失败");
}
}
/**
* 根据config.xml文件中的key获取对应的class类实例
* @param key
* @return bean
*/
public static Object getBean(String key) {
Object bean=null;
try {
//得到key对应的value值,并创建对象
String className = prop.getProperty(key);
bean = Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
在以上代码中,首先声明了properies类的对象prop,利用反射机制(ClassName.class)和ClassLoader类加载器中的getResourceAsStream(),将配置文件以流的形式读取出来,prop加载此流的信息,读取到配置文件。
prop对象根据传入key获取对应的value,value就是类的全限定类名,根据此类名利用反射机制创建想要对象。并返回给调用者。
第二步:在根目录下创建config.properies文件EmpService=com.yd.service.EmpServiceImpl
EmpDao=com.yd.dao.EmpDaoImpl
第三步:在EmpController类中添加如下代码//工厂方式解耦
//获取Service接口的子类实例
private EmpService service=(EmpService) BeanFactory.getBean("EmpSerice");
//获取Dao接口的子类实例
private EmpDao empDao=(EmpDao) BeanFactory.getBean("EmpDao");
@Test
public void testAddEmp() {
System.out.println("工厂方式调用service层的方法添加员工信息");
service.addEmp();
}
工厂模式本质就是利用Java的反射机制和ClassLoader类加载器,为开发者提供一个创建类的统一接口。开发者只需要调用Beanfactory(),配合.properties文件,就能创建实例,调用方法。
基于工厂模式,大佬和高手开发出了强大的工具spring和springboot,spring以IOC(Inverse Of Control:控制反转)和AOP(Aspact Oriented Programming:面向切面编程)为核心,整合开源世界的大多数第三方框架,成为使用最多的JavaEE企业应用开源框架。
spring的本质就是管理程序的对象,即创建对象和维护对象之间的关系。