面向接口编程在Java web 三层架构的应用与使用工厂模式解决问题
2010-10-20 19:56
756 查看
面向接口编程在Java web 三层架构的应用与使用工厂模式解决问题
为什么要面向接口编程:
在应用中,我们一般都是面向接口编程的,这样有利于系统的扩展与移植。就像Java Web中的三层架构:展现层、业务逻辑层、数据持久层一样,上层都是调用下层的接口。因为一旦下层实现改变:比如持久层从数据库操作更换为文件操作,上层因为调用下层的接口而不用更改任何代码,利于系统扩展与移植。
面向接口编程的思路要点:
举一个例子,现在要添加一个用户,数据持久层接口如下所示:
而其两个实现分别如下:
一、数据库实现代码:
二、文件实现类代码如下:
这样业务逻辑层代码如下所示:
面向接口编程的问题:
这样如果要使得用户保存从数据库更换为文件,就要修改构造方法中的userInfoDao = new UserInfoDao4SQL();这一行代码,这样就有不符合修改扩展的原则,因为一旦要更改实现,就要更改代码。
面向接口编程问题的解决思路:
具体的做法是将要更改的代码提取到配置文件里,就如同数据库的配置文件,这样就可以直接修改配置文件,而不用修改代码了。这里我们介绍一种方法,叫做工厂模式方法,代码如下:
配置文件InterfaceFactory.xml代码如下:
类InterfaceFactory采用dom4j来解析xml文件,然后在getBean()方法中使用反射机制Class.getName()来生成要采用的接口实现类。并且将实现类放在Map中,这样以后要用到就直接从map中取,提高了效率。配置文件采用了数据库实现,如果要采用文件实现则将配置文件转换为:
这样业务逻辑层的代码修改为如下,这样以后就可以不用修改代码写该配置文件即可完成:
为什么要面向接口编程:
在应用中,我们一般都是面向接口编程的,这样有利于系统的扩展与移植。就像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); } }
相关文章推荐
- 面向接口编程在Java web 三层架构的应用与使用工厂模式解决问题
- 三层架构中 工厂模式和单例模式的使用
- 实战才是王道:工厂模式、三层架构、反射、多数据库问题
- python:使用OO和工厂模式解决问题
- Win10使用兼容性模式来解决应用无法运行的问题
- 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
- Unity应用架构设计(2)——使用中介者模式解耦ViewModel之间通信
- iOS开发:基本设计模式(下)-使用设计模式解决问题
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- IOS开发:基本设计模式(下)-使用设计模式解决问题
- 开发Windows商店应用时使用SmsDevice类API遇到的Access Denied问题解决方法
- 用单例模式解决临界区(CRITICAL_SECTION)的使用问题
- 三层架构,MVC模型,工厂设计模式的粗浅理解 转
- redis在应用中使用连接不释放问题解决
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- 使用观察者模式解决包相互依赖的问题
- 使用 IntelliJ IDEA 2016和Maven创建Java Web项目的详细步骤及相关问题解决办法
- Java web应用中的常见字符编码问题的解决方法