面向接口编程在Java web 三层架构的应用与使用工厂模式解决问题

本文探讨了面向接口编程在JavaWeb三层架构中的应用,并通过实例展示了如何利用工厂模式简化系统扩展过程,提高代码复用性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面向接口编程在Java web 三层架构的应用与使用工厂模式解决问题

为什么要面向接口编程:

在应用中,我们一般都是面向接口编程的,这样有利于系统的扩展与移植。就像Java Web中的三层架构:展现层、业务逻辑层、数据持久层一样,上层都是调用下层的接口。因为一旦下层实现改变:比如持久层从数据库操作更换为文件操作,上层因为调用下层的接口而不用更改任何代码,利于系统扩展与移植。

面向接口编程的思路要点:

举一个例子,现在要添加一个用户,数据持久层接口如下所示:

package kane; import java.util.List; import kane.UserInfo; /** * UserInfoDao层接口 * @author kane */ public interface UserInfoDao { //添加注册用户基本信息 public void addUserInfo(UserInfo u); }

而其两个实现分别如下:

一、数据库实现代码:

package kane; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import kane.UserInfo; import kane.DBUtility; /** * UserInfoDao接口实现类 * @author kane */ public class UserInfoDao4SQL implements UserInfoDao { public void addUserInfo(UserInfo u) { Connection conn = null; PreparedStatement pstmt = null; try { conn = DBUtility.getConnection(); conn.setAutoCommit(false); String sql = "insert into user_info(id,username,password) values(?,?,?)"; pstmt = conn.prepareStatement(sql); pstmt.setInt(1, u.getId); pstmt.setString(2, u.getUsername()); pstmt.setString(3, u.getPassword()); pstmt.execute(); conn.commit(); } catch (SQLException e) { try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); } finally { DBUtility.closePreparedStatement(pstmt); DBUtility.closeConnection(); } } }

二、文件实现类代码如下:

package kane; import java.; import java.util.ArrayList; import java.util.List; import kane.UserInfo; /** * UserInfoDao接口实现类 * @author kane */ public class UserInfoDao4File implements UserInfoDao { public void addUserInfo(UserInfo u) { //文件操作实现代码…….. } }

这样业务逻辑层代码如下所示:

package kane; import java.sql.Connection; import java.util.List; import kane.UserInfoDao; import kane.UserInfo; /** * UserInfoManage业务逻辑 * * @author kane * */ public class UserInfoManage { private UserInfoDao userInfoDao = null; public UserInfoManage () { userInfoDao = new UserInfoDao4SQL(); } /** public UserInfoManage () { userInfoDao = new UserInfoDao4File(); userInfoDao = (UserInfoDao) InterfaceFactory.getInstance().getBean( UserInfoDao.class); } */ public void addUserInfo(UserInfo u) { userInfoDao.addUserInfo(u); } }

面向接口编程的问题

这样如果要使得用户保存从数据库更换为文件,就要修改构造方法中的userInfoDao = new UserInfoDao4SQL();这一行代码,这样就有不符合修改扩展的原则,因为一旦要更改实现,就要更改代码。

面向接口编程问题的解决思路:

具体的做法是将要更改的代码提取到配置文件里,就如同数据库的配置文件,这样就可以直接修改配置文件,而不用修改代码了。这里我们介绍一种方法,叫做工厂模式方法,代码如下:

package kane; import java.util.HashMap; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * 抽取出相同的创建接口对象的方法——采用InterfaceFactory创建各个接口产品 * @author kane 使用单例模式 */ public class InterfaceFactory { private static InterfaceFactory instance = null; private Document document = null; private Map<String, Object> beanMap = new HashMap<String, Object>(); private InterfaceFactory() { try { document = new SAXReader().read(Thread.currentThread() .getContextClassLoader().getResourceAsStream( "InterfaceFactory.xml")); } catch (DocumentException e) { e.printStackTrace(); } } public static InterfaceFactory getInstance() { if (instance == null) { instance = new InterfaceFactory(); } return instance; } /** * 如果Map中有该Bean,则直接返回,否则创建该Bean并将其加入到Map中 * @目的是使得加载效率更高 * @param id * @return 要取得的Bean */ @SuppressWarnings("unchecked") public synchronized Object getBean(Class c) { Object bean = null; bean = beanMap.get(c.getName()); if (bean == null) { try { Element e = (Element) document .selectObject("//interface[@id=/"" + c.getName() + "/"]"); String className = e.attributeValue("class"); bean = Class.forName(className).newInstance(); beanMap.put(c.getName(), bean); } catch (InstantiationException e1) { e1.printStackTrace(); } catch (IllegalAccessException e2) { e2.printStackTrace(); } catch (ClassNotFoundException e3) { e3.printStackTrace(); } } return bean; } }

配置文件InterfaceFactory.xml代码如下:

<?xml version="1.0" encoding="UTF-8"?> <bean> <interface id="kane.UserInfoDao" class=" kane.UserInfoDao4SQL" /> </bean>

InterfaceFactory采用dom4j来解析xml文件,然后在getBean()方法中使用反射机制Class.getName()来生成要采用的接口实现类。并且将实现类放在Map中,这样以后要用到就直接从map中取,提高了效率。配置文件采用了数据库实现,如果要采用文件实现则将配置文件转换为:

<?xml version="1.0" encoding="UTF-8"?> <bean> <interface id="kane.UserInfoDao" class=" kane.UserInfoDao4File" /> </bean>

这样业务逻辑层的代码修改为如下,这样以后就可以不用修改代码写该配置文件即可完成:

package kane; import java.sql.Connection; import java.util.List; import kane.UserInfoDao; import kane.UserInfo; import kane.InterfaceFactory; /** * UserInfoManage业务逻辑 * * @author kane * */ public class UserInfoManage { private UserInfoDao userInfoDao = null; public UserInfoManage () { userInfoDao = (UserInfoDao) InterfaceFactory.getInstance().getBean( UserInfoDao.class); } public void addUserInfo(UserInfo u) { userInfoDao.addUserInfo(u); } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值