我们在学习java的时候,尤其到了后面学习框架的时候,我们总会被一些java中的设计模式打交道,每次我们都还感觉比较难,在这里,我就对我们其中的一种工厂模式,来做一个简单的分析
1,什么是工厂模式?
所谓的工厂模式,就是我们创建对象的方式发生了改变,原来的创建对象,都是由我们在使用的时候,通过new进行创建,而现在我们再创建对象时候,而是通过我们的工厂来帮我们创建对象(其实来说就是通过别的方式,创建出我们所需要的对象,例如我们想给我们的女朋友送一个情人节礼物--小熊娃娃,如果要是没有做娃娃的工厂帮我们去做这个娃娃,那我们就只能自己动手去做了,大家就可以想想工厂所能带给我们好处)
2,现做如下的简单的代码演示
1) 准备阶段
(1)创建实体类User
/**
* 创建实体类
* 提供setter 和 getter
* 重写toString()方便查看数据
* */
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
(2) 创建UserDao
public interface UserDao {
/**
* 根据用户id查找User
* */
public abstract User findUserById(Integer id);
}
(3) 创建UserDaoImpl
public class UserDaoImpl implements UserDao {
@Override
public User findUserById(Integer id) {
/**
* 本来查询数据需要从数据库里面进行查询
* 现在我在这手动创建一个User来代替数据库里面的数据
* */
User u = new User();
u.setId(2022001);
u.setName("张三三");
// 返回当前用户
return u;
}
}
2) 测试阶段
(1) 没有使用工厂模式代码
public class BeanFactoryTest {
@Test
public void testBeanFactory(){
// 原来我们没有使用工厂的时候,在这里我们需要通过new的方式来创建对象
UserDao userDao = new UserDaoImpl();
//通过id查询用户
User user = userDao.findUserById(2022001);
System.out.println(user);
}
}
查询结果如图:
当我们再操作 UserDao userDao = new UserDaoImpl();试想现在我们使用的数据库是mysql 的实现方式,到了某一天我们需要更换底层数据的实现方式,那么我们就需要创建出新的UserDao实现类对象,这里的UserDaoImpl将不在可能被使用,这时这里就会报错,我们还需要更改这里的代码,那我们有没有一种方式,我们尽量更改更少,添加一些新的代码时,对现有的代码做更小的改动,这里工厂模式就可以帮我们做到
到这我来说一下下面我们为什么要使用工厂模式: 工厂模式最大的一个好处就是之后,可以帮我们进行代码的解耦合,我们知道编写代码的要求是高内聚,低耦合
(2)使用工厂模式
我们需要先创建出一个配置文件 dao.properties
mysql.impl=com.offcn.dao.impl.UserDaoImpl
# 可能到了莫一天我们需要更改数据的实现方式,那我们就可以在这里进行修改,其余的代码不发生改变
# oracle.impl=com.offcn.dao.impl.UserDaoOracleImpl
之后我们在创建一个工厂类BeanFactory
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
//创建Properties对象
private static Properties p = new Properties();
private static String value;
/**
* 读取我们的配置文件
* */
static {
// 将配置文件里面的数据,加载到流中
InputStream is =
BeanFactory.class.getClassLoader().getResourceAsStream("dao.properties");
try {
// 将流与我们的Properties进行关联
p.load(is);
//获得集合里面的数据,通过key获取value值
value = p.getProperty("mysql.impl");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 这里我们可以更改,获取UserDaoImpl具体的实现类
*/
public static UserDao getInstance() {
try {
// 通过反射获取value值
Class<?> aClass = Class.forName(value);
// 通过newInstance() 创建对象
UserDao userDao = (UserDao) aClass.newInstance();
// 返回UserDao对象
return userDao;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
之后测试类里面的代码需要做如下改变
package com.offcn.beanfactorytest;
import com.offcn.bean.User;
import com.offcn.dao.UserDao;
import com.offcn.dao.impl.UserDaoImpl;
import com.offcn.factory.BeanFactory;
import org.junit.Test;
public class BeanFactoryTest {
@Test
public void testBeanFactory() {
// 原来我们没有使用工厂的时候,在这里我们需要通过new的方式来创建对象
//UserDao userDao = new UserDaoImpl();
// 这里我们再获取代码的时候,通过工厂获得
UserDao userDao = BeanFactory.getInstance();
User user = userDao.findUserById(2022001);
System.out.println(user);
}
}
结果如下:
在工厂模式中,我们发现所写的代码,中已经看不到new的存在了,但是我们还能获取到对象,来进行使用,包括后期在进行改进代码的时候,我们也只需要添加,和修改配置文件里面的内容即可