您当前的位置: 首页 > 

liaowenxiong

暂无认证

  • 1浏览

    0关注

    1171博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式之工厂模式

liaowenxiong 发布时间:2021-03-01 10:23:03 ,浏览量:1

文章目录
    • 工厂类介绍
    • 工厂模式演示步骤
      • 步骤1:新建 DAOFactory.java,在 DAOFactory 中确定 EmployeeDAO 接口的具体实现类
      • 步骤 2:Servlet 中增删改查操作都使用 DAOFactory 生成具体实例
    • DAO 及工厂模式
      • 项目结构
      • 参考代码
    • 改进 DAO 工厂模式
      • 步骤 1:新建配置文件 dao_config.properties
      • 步骤 2:新建读取配置文件的工具类 ConfigUtil.java
      • 步骤 3:修改 DAOFactory.java

工厂类介绍

定义一个类,由该类来提供程序需要使用的某些对象,这个类就是工厂类,工厂类封装了对象的创建细节,为调用者提供符合要求的对象。示意图如下:

在这里插入图片描述

现在做这样一个假设,假如我们的底层数据访问不再使用 JDBC,而采用 Hibernate。 那么我们需要为 EmployeeDAO 增加一个实现 EmployeeDAOHibernateImpl.java 并且修改之前的代码,DelEmpServlet、AddEmpServlet、ListEmpServlet、LoadEmpServlet、 ModifyEmpServlet 都要做相应修改,如下所示:

注:模拟实现 1) EmployeeDAOHibernateImpl.java


/**
* DAO 的另外一个实现
*/
public class EmployeeDAOHibernateImpl implements EmployeeDAO { 
    public void delete(long id) throws Exception {}
    
    public List findAll() throws Exception {
    	System.out.println("Hibernate 实现 findAll ...");
    	return null;
    }
    
    public Employee findById(long id) throws Exceptino {
        return null;
    }

    public void save(Employee e) throws Exception {}
    
    public void update(Employee e) throws Exception {}
    
}

2) DelEmpServlet.java


public class DelEmpServlet extends HttpServlet { 
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
    	long id = Long.parseLong(request.getParameter("id"));
    	try {
   			// EmployeeDAO dao = new EmployeeDAOJdbcImpl();
   			EmployeeDAO dao = new EmpployeeDAOHibernateImpl();
   			dao.delete(id);
   			response.sendRedirect("list");
    	} catch (Exception e) {
    		e.printStackTrace();
    		throw new ServletException(e);

    	}
	}
}

3) AddEmpServlet.java(略)

4) ListEmpServlet(略)

5) LoadEmpServlet(略)

6) ModifyEmpServlet(略)

然而,我们希望尽量不修改写好的代码(Servlet 代码)。 此时,我们可以使用工厂模式

工厂模式演示步骤 步骤1:新建 DAOFactory.java,在 DAOFactory 中确定 EmployeeDAO 接口的具体实现类

在这里插入图片描述

步骤 2:Servlet 中增删改查操作都使用 DAOFactory 生成具体实例

在这里插入图片描述

ok,当查询数据库需要不同实现时,只要修改工厂类 DAOFacory 即可,这样我们就不用修改每个 Servlet 了

提问 :这样的方式已经使代码的可扩展性提高很多,但是我们还需要修改 DAOFactory,如果我们不想修 改 DAOFacotry 该如何实现?

回答:使用配置文件,写一个类专门读取配置文件(属性文件)的 value,需要变更时,修改配置文件即可

DAO 及工厂模式 项目结构

在这里插入图片描述

参考代码

1) Employee.java

package entity; 
/**
* 实体类
* @author liaowenxiong
*/
public class Employee { 
    private long id;
    private String name; 
    private double salary; 
    private int age;
    
	public int getAge() {
		return age;
	} 

	public void setAge(int age) {
		this.age = age;
	}
	
	public long getId() {
	return id;
	}
	
	public void setId(long id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	} 

	public void setName(String name) {
	this.name = name;
	}
	
	public double getSalary() {
		return salary;
	} 

	public void setSalary(double salary) {
		this.salary = salary;
	}
}

2) EmployeeDAO.java

package dao;
import java.util.List; 
import entity.Employee;
/**
* DAO 接口
* @author liaowenxiong
*/
public interface EmployeeDAO {
	/*
	* public void save(Employee e) throws SQLException;
	* 这种方式不好,因为出现了 jdbc 的异常类,这就要求实现该方法只能使用 jdbc 
	* 
	*/ 

	public List findAll() throws Exception; 

	public void delete(long id) throws Exception; 

	public void save(Employee e) throws Exception;

	public Employee findById(long id) throws Exception;

	public void update(Employee e) throws Exception;

}

3) EmployeeDAOJdbcImpl.java

package dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement; 
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import util.DBUtil;
import dao.EmployeeDAO; 
import entity.Employee;

public class EmployeeDAOJdbcImpl implements EmployeeDAO { 
	/*
	* 查询员工列表
	*/
	public List findAll() throws Exception { 
	    Connection conn = DBUtil.getConnection(); 
		Statement stat = conn.createStatement(); 
		ResultSet rst = stat.executeQuery("select * from t_emp");
		List employees = new ArrayList();
		while (rst.next()) {
			Employee e = new Employee();
			e.setId(rst.getLong("id")); 
			e.setName(rst.getString("name")); 
			e.setSalary(rst.getDouble("salary")); 
			e.setAge(rst.getInt("age"));
			employees.add(e); 
		}
	
		// 关闭数据库连接
		DBUtil.close(conn);	
		return employees; 
	}
	
	
	/*
	* 删除员工
	*/
	public void delete(long id) throws Exception {
		Connection conn = DBUtil.getConnection(); 
		PreparedStatement prep = conn.prepareStatement("delete from t_emp where id = ?");
		prep.setLong(1, id);
		prep.executeUpdate();
		DBUtil.close(conn); 

 	}

	/*
	* 保存员工
	*/
	public void save(Employee e) throws Exception {
		Connection conn = DBUtil.getConnection(); 
		PreparedStatement prep = conn.prepareStatement( "insert into t_emp(name,salary,age) values(?,?,?)"); 			prep.setString(1, e.getName());
		prep.setDouble(2, e.getSalary());
		prep.setInt(3, e.getAge()); 
		prep.executeUpdate(); 
		DBUtil.close(conn);
	}

	/*
	* 通过员工ID号查询员工信息
	*/
	public Employee findById(long id) throws Exception {
		Connection conn = DBUtil.getConnection(); 
		PreparedStatement prep = conn.prepareStatement( "select * from t_emp where id = ?"); 
		prep.setLong(1, id);
    	ResultSet rst = prep.executeQuery();
		Employee e = null; 
		if (rst.next()) { // 这样的写法只能查询一个员工,如果查询到多个员工,也只是获取结果集中的第一个员工的数据
			e = new Employee(); 
			e.setId(id);
			e.setName(rst.getString("name"));
			e.setSalary(rst.getDouble("salary"));
			e.setAge(rst.getInt("age"));
	    } 
		DBUtil.close(conn); 
		return e;
 	}
 	public void update(Employee e) throws Exception {
		Connection conn = DBUtil.getConnection(); 
		PreparedStatement prep = conn.prepareStatement( "update t_emp" +
		"set name = ?, salary = ?, age = ?" +
		"where id = ?"); 
		prep.setString(1, e.getName());
 		prep.setDouble(2, e.getSalary()); 
 		prep.setInt(3, e.getAge()); 
 		prep.setLong(4, e.getId());
		prep.executeUpdate();
		DBUtil.close(conn); }
	}

4) EmployeeDAOHibernateImpl.java

package dao.impl; 
import java.util.List;
import dao.EmployeeDAO; 
import entity.Employee;

/**
* dao 的另外一个实现
* @author liaowenxiong
*/

public class EmployeeDAOHibernateImpl implements EmployeeDAO {
    public void delete(long id) throws Exception {}
    
 	public List findAll() throws Exception {
		System.out.printl n("hibernate 实现 findAll...");
		return null;
	}
	
    public Employee findById(long id) throws Exception {
		return null;
	}
	
	public void save(Employee e) throws Exception {}
	
	public void update(Employee e) throws Exception {} 
}

5) TestDAO.java

package test; 
import java.util.List;
import dao.EmployeeDAO;
import dao.impl.EmployeeDAOJdbcImpl;
import entity.Employee;

/**
* 测试类,用来测试程序用
*/

public class TestDAO {
	public static void main(String[] args) throws Exception {
		EmployeeDAO dao = new EmployeeDAOJdbcImpl();
		// 查找全部
		List employees = dao.findAll(); 
		System.out.println(employees.size());
		
	 	// 删除 
 		// dao.delete(1);
 
		// 插入数据
		// Employee e = new Employee();
		// e.setName("abc9"); 
		// e.setSalary(1000);
		// e.setAge(22); 
		// dao.save(e);
 
		// 按id查找
		// Employee e = dao.findById(7); 
		// System.out.println(e.getName());
	} 
}

6) DAOFactory.java

package util;
import dao.impl.EmployeeDAOHibernateImpl; 
import dao.impl.EmployeeDAOJdbcImpl;

/**
* dao 工厂,为调用者提供 dao 实现类的实例
* @author liaowenxiong
*/

public class DAOFactory {
    public static Object getInstance(String type) { 
		Object obj = null;
		if (type.equals("EmployeeDAO")) {
			//obj = new EmployeeDAOJdbcImpl(); 
			obj = new EmployeeDAOHibernateImpl();
		}
		return obj; 
	}
}

7) DBUtil.java

package util;
import java.sql.Connection; 
import java.sql.DriverManager;
import java.sql.SQLException; 

/**
* jdbc 工具类,提供获得连接、关闭连接的方法
* @author liaowenxiong
*/

public class DBUtil {

	/**
	* 获取数据库连接对象
	*/
	public static Connection getConnection() throws Exception {
		Connection conn = null;
		try {
		// 内部会通过类加载器将 Driver 读取到内存,得到一个用于保存 Driver 信息的 Class实例
		Class.forName("com.mysql.jdbc.Driver"); 
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qpw","root","root");
		} catch (Exception e) {
		e.printStackTrace(); 
		throw e;
		}
		return conn; 
	}

	/**
	* 关闭数据库连接
	*/
	public static void close(Connection conn) {
		if(conn!= null){ 
			try {
				conn.close();
			} catch (SQLException e) { 
				e.printStackTrace();
			} 
		}
	}
	
 	//用于测试 DBUtil
	public static void main(String[] args) throws Exception {
		System.out.println(getConnection()); 
	}
}

8) AddEmpServlet.java

package web;
import java.io.IOException; 
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager; 
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;
import dao.EmployeeDAO;
import dao.impl.EmployeeDAOJdbcImpl; 
import entity.Employee;

public class AddEmpServlet extends HttpServlet { 
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
	
		/*
		* 指定字符编码的代码要放在 getParameter() 执行之前,
		* 因为客户端传过来的参数内容可能含有中文字符,常规下是
		* 使用 utf-8 编码后再传给服务端,服务端接收请求数据包
		* 后,要读取内容就需要解码,所以就要提前设置好用于解码
		* 的字符编码类型
		*/ 
	
		request.setCharacterEncoding("utf-8"); // 指定用来解码的字符编码为 utf-8
		String name = request.getParameter("name"); 
		double salary = Double.parseDouble(request.getParameter("salary"));
		int age = Integer.parseInt(request.getParameter("age")); 
		System.out.println("name:" + name);
		System.out.println("salary:" + salary); 
		System.out.println("age:" + age); 
		
		Employee e = new Employee(); 
		e.setName(name);
		e.setSalary(salary);
		e.setAge(age); 
		
		// EmployeeDAO dao = new EmployeeDAOJdbcImpl(); 
		// 使用工厂模式
		EmployeeDAO dao = (EmployeeDAO)DAOFactory.getInstance("EmployeeDAO");
		
		try {
			// 将员工信息保存到数据库
			dao.save(e);
		
		} catch (Exception e) {
			// step1 先记录日志
			e.printStackTrace();
			// step2 抛出
			throw new ServletException(e);
		}
	
		response.sendRedirect("list"); 
		} 
}

9) DelEmpServlet.java

package web;
import java.io.IOException; 
import java.sql.Connection;
import java.sql.DriverManager; 
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;
import dao.EmployeeDAO;
import dao.impl.EmployeeDAOHibernateImpl; 
import dao.impl.EmployeeDAOJdbcImpl;

public class DelEmpServlet extends HttpServlet {
    public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { 
	    long id = Long.parseLong(
	    request.getParameter("id")); 
	    // EmployeeDAO dao = new EmployeeDAOJdbcImpl();
		// EmployeeDAO dao = new EmployeeDAOHibernateImpl();
		// 使用工厂模式
		EmployeeDAO dao = (EmployeeDAO)DAOFactory.getInstance("EmployeeDAO");
	    try {	
			dao.delete(id);
			
		}catch(Exception e){
			e.printStackTrace();
			throw new ServletException(e);
		} 
		response.sendRedirect("list"); 
		}
}

10) ListEmpServlet.java

package web;
import java.io.IOException;
import java.io.PrintWriter; 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet; 
import java.sql.SQLException;
import java.sql.Statement; 
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;
import util.DAOFactory;
import dao.EmployeeDAO;
import dao.impl.EmployeeDAOJdbcImpl; 
import entity.Employee;
 
public class ListEmpServlet extends HttpServlet { 
	public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { 
		// 使用 dao 访问数据库
		try {
			// EmployeeDAO dao = new EmployeeDAOJdbcImpl();
			// 使用工厂模式
			EmployeeDAO dao = (EmployeeDAO)DAOFactory.getInstance("EmployeeDAO");
			List employees = dao.findAll(); 
			//使用查询得到的结果,生成一个表格 
			response.setContentType("text/html;charset=utf-8");
			PrintWriter out = response.getWriter();
			out.println("");
			out.println("id姓名薪水年龄操作"); 
			for (int i = 0; i  

addEmpServlet
web.AddEmpServlet 


 
listEmpServlet
web.ListEmpServlet 



delEmpServlet 
web.DelEmpServlet
 


loadEmpServlet
web.LoadEmpServlet
 


modifyEmpServlet
web.ModifyEmpServlet 


 
addEmpServlet
/add 
 

 
listEmpServlet
/list 


 
delEmpServlet 
/del
 


loadEmpServlet 
/load
 


modifyEmpServlet 
/modify
 


500
/error.html 



14) addEmp.html




addEmp


 

添加雇员
姓名: 
薪水:
年龄:
 

 


       

15) error.html



 
Insert title here


发生了系统错误,请稍后
重试 


改进 DAO 工厂模式

我们在实现“数据库访问技术由 JDBC 更改为 Hibernate”的时候,还需要修改 DAOFactory,如果我们不想修改 DAOFacotry 该如何实现?

步骤 1:新建配置文件 dao_config.properties

在这里插入图片描述

步骤 2:新建读取配置文件的工具类 ConfigUtil.java
public class ConfigUtil {
    private static Properties props = new Properties();

    static {
        ClassLoader loader = ConfigUtil.class.getClassLoader();
        InputStream ips = loader.getResourceAsStream("util/dao_config.properties");
        try {
            props.load(ips);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static String getValue(String key) {
        return props.getProperty(key);
    }

    /**
     * @return
     * @MethodName
     * @Author liaowenxiong
     * @Description TODO
     * @Date 下午4:10 2021/3/31
     * @Param
     */
    public static void main(String[] args) {
        System.out.println(getValue("EmployeeDAO"));
    }

}
步骤 3:修改 DAOFactory.java
public class DAOFactory {
    /**
     * @MethodName
     * @Author liaowenxiong
     * @Description 读取属性文件,根据传入的 key 获得对应的 value,key 是接口名称,value 就是实现类的包路径名称,
     * 然后通过反射机制创建实现类的实例并返回给调用者
     * @Date 下午5:08 2021/3/31
     * @Param
     * @return
     */
    public static Object getInstance(String type) {
        Object obj = null;
        String className = ConfigUtil.getValue(type);
        // newInstance 已经过时了
        // obj = Class.forName(className).newInstance();
        try {
            obj = Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        
        return obj;
    }
}

在以后的修改,我们只需要修改配置文件 dao_config.properties 即可。

关注
打赏
1661566967
查看更多评论
立即登录/注册

微信扫码登录

0.0484s