我们都知道在web开发时经常使用三层架构(web、service、dao),每一层有着自己的实现类,而通过对实现类进行抽取方法形成接口,每一层通过接口进行上下层之间的耦合。例如在业务service层和数据访问dao层之间,当dao层写好了对数据库的增删改查方法时,抽取成dao接口,而在service如果要调用dao层的方法就只要使用dao接口即可,但是关键是在service层使用dao接口的时候,如何获取dao接口的实现对象是个问题。

  案例:在数据访问dao层,编写好了一个对数据库中表user的增删查改方法,封装于UserDaoImpl实现类中,将UserDaoImpl实现类中的方法抽取出来成UserDao接口,那么如果在service中要使用User对象,那么就必须要使用到dao层中有关User的操作,由多态的灵活性,在service层中只要使用UserDao接口即可,但是光有一个接口引用对象没有用,我们必须要有UserDaoImpl这样的真正的实现类才能构建(new)出对象,难道要在service层使用UserDao dao = new UserDaoImpl();这样的代码?这样明显使dao层的实现类侵入了service层中,如果将来我们的实现类从UserDaoImpl变成了UserDaoJdbcImpl或者UserDaoXmlImpl这样的岂不是要在service层的代码中改动?

  

  如何对不同层的代码进行解耦,关乎整个应用的灵活性,下面我们就来使用工厂模式来结局这个问题。

  创建一个工程,为了简洁说明上面的例子,我们就创建四个类或接口就好了,结构如下图所示:

  

  在com.fjdingsd.daoimpl包中的dao层的实现类,这里面封装了一个对User对象的增删改查的具体实现方法(方法内容略):

 1 package com.fjdingsd.daoimpl;
 2 public class UserDaoImpl implements UserDao {
 3     @Override
 4     public void insert(){
 5         。。。//添加User对象
 6     }
 7
 8     @Override
 9     public void delete() {
10         。。。//删除User对象
11     }
12
13     @Override
14     public void update() {
15         。。。//修改User对象
16     }
17
18     @Override
19     public void find() {
20         。。。//查找User对象
21     }
22 }

View Code

  将该dao对User的实现类方法抽取到UserDao接口中去:

1 package com.fjdingsd.dao;
2 public interface UserDao {
3     public abstract void insert();
4     public abstract void delete();
5     public abstract void update();
6     public abstract void find();
7 }

View Code

  如果没有使用工厂模式,那么因为没什么好的方法,所以只能在service层的实现类中直接使用UserDaoImpl来构建对象,但是我们这里使用工厂模式,来避免这个问题。使用工厂模式为了便于灵活性,我们将dao层接口和dao层的实现类在配置文件factory.properties中定义,以dao接口名作为关键字,以dao实现类的全名(包名+类名)作为关键字的值。以dao层中对User对象为例,在factory.properties中定义如下:

    UserDao=com.fjdingsd.dao.impl.UserDaoImpl

  使用这样配置的好处在于以后对于UserDao接口,如果我们想更换实现类,只要改动配置文件即可,代码中完全不需要修改。

  在工厂类DaoFactory中的代码如下:

 1 package com.fjdingsd.factory;
 2 public class DaoFactory {
 3
 4     private static DaoFactory instance = new DaoFactory();
 5     private Properties config = new Properties();
 6
 7     private DaoFactory(){
 8         InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("factory.properties");    //读取配置文件装载进输入流
 9         try {
10             config.load(in); //将配置文件封装进Properties对象中
11
12         } catch (IOException e) {
13             e.printStackTrace();
14         }
15     }
16
17     public static DaoFactory getInstance() {
18         return instance;
19     }
20
21     public <T> T createDao(Class<T> clazz) {
22         String interfaceName = clazz.getSimpleName();//获取配置文件中的接口关键字
23         String className = config.getProperty(interfaceName); //根据接口名获取配置文件中的具体实现类完整名称
24         try {
25             T bean = (T) Class.forName(className).newInstance();//使用反射创建实现类的一个实例对象
26             return bean;
27         } catch (Exception e) {
28             throw new RuntimeException(e);
29         }
30     }
31 }

View Code

  这样在service层的实现类中以dao层接口引用具体dao层的实现类就不需要直接创建对象,直接使用工厂模式加泛型即可,如下代码所示:

1 package com.fjdingsd.service.impl;
2 public class BussinessServiceImpl {
3
4     //UserDao uDao = new UserDaoImpl();  以前未使用工厂模式加泛型之前的写法
5     UserDao uDao = DaoFactory.getInstance().createDao(UserDao.class);
6     。。。//其他代码,此处略
7 }

View Code

分析:

  工厂模式负责一部分接口对象的实现类生成,建议使用单例模式,上面的示例也是这样。工厂模式使用单例的好处在于如果要修改代码,那么只要找工程即可,如果每一个接口的实现类都配一个工厂,那么工厂会太多,不利于程序的简洁。

  在工厂中,为某个接口创建实现类对象,我们使用 配置文件+泛型 的方法,配置文件前面已经说过了,如果想更换某个接口的实现类只要修改配置文件即可。而使用泛型,可以很优雅地避免对某个具体的接口都要写一个方法来创建对象,如上例在工厂中的createDao方法,只要根据配置文件信息就可以为接口获取一个对应的实现类,同时要注意在配置文件中的关键字和值一定要是和已经定义好的接口名和类名匹配。请好好品尝消化上面的例子。

转载于:https://www.cnblogs.com/fjdingsd/p/5272323.html

使用工厂模式与泛型对三层架构的每一层进行解耦相关推荐

  1. 桥接模式的应用之三层架构中的业务逻辑层(BLL)与数据访问层(DAL)的解耦

    各层的作用 ①用户界面层:只负责显示和采集用户操作. ②业务逻辑层:负责UI和DAL层之间的数据交换,是系统架构中体现核心价值的部分.它关注点主要集中在业务规则的制定.业务流程的实现和业务需求的有关系 ...

  2. 抽象工厂模式升级版————泛型化实现

    引言 今天回看之前总结的抽象工厂模式的实现<Java常用设计模式----抽象工厂模式>,聚焦于抽象工厂模式的缺点,试着改进了一下. 回顾一下抽象工厂模式的缺点: 在添加新的产品类型时,难以 ...

  3. 阿里为什么建议给MVC三层架构多加一层Manager层?

    MVC三层架构 我们在刚刚成为程序员的时候,就会被前辈们 "教育" 说系统的设计要遵循 MVC(Model-View-Controller)架构.它将整体的系统分成了 Model( ...

  4. java框架三层架构是_MVC框架模式和Javaweb经典三层架构

    一.MVC设计模式 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Co ...

  5. JAVA 工厂模式与泛型之趣味奶茶店

    一.趣味咖啡厅的开张 作为拆二代的我,决定不再继续挥霍,想搞搞投资,准备开一家奶茶店... 由于SpringBoot非常便捷与火爆,所以奶茶店采用SpringBoot搭建. 二.创建订单对象 首先,忽 ...

  6. 三层架构之抽象工厂加反射mdash;mdash;实现数据库转换

    在做系统的时候有意识的用到了抽象工厂这个设计模式,主要解决的是数据库更换的问题. 下面就以简单的登录来逐步的分析一下这个模式. 经典的三层架构 数据库如下 1.      一般的数据库连接方式 界面层 ...

  7. java ssh三层架构_SSH和三层架构的MVC模式的对应关系

    1.MVC(Model-View-Controller)设计模式: 首先让我们了解下MVC(Model-View-Controller)的概念: MVC全名是Model View Controller ...

  8. MVC模式与三层架构的区别

    MVC模式与三层架构的区别 原文地址:http://www.cnblogs.com/yourshj/p/5197310.html 之前总是混淆MVC表现模式和三层架构模式,为此记录下. 三层架构和MV ...

  9. 三层架构和MVC模式

    1.三层架构 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了" ...

最新文章

  1. 重磅!教育部:不得将发论文和物质奖励挂钩,防止高额奖励论文
  2. mysql多实例安装配置演示
  3. Tomcat - Tomcat 8.5.55 启动过程源码分析阶段二_load加载初始化
  4. 【学习笔记】CO-PA 简介
  5. PHPstrom怎样设置浏览器
  6. ASP.NET 网站路径
  7. CVPR2021开源项目,带你傲游宇宙!
  8. 2017.10.14 【FOTILE模拟赛】L 失败总结
  9. 去中心化保险协议InsurAce完成100万美元种子轮融资,DeFiance Capital领投
  10. GitHub的实现是否是基于此语言的支持网络编程性呢?
  11. win10无法访问ftp服务器
  12. asp小偷转html,ASP之XMLHTTP小偷程序的简单代码范例
  13. APMCM亚太地区数学建模历年赛题
  14. linux运行roon,Roon + HQPlayer + NAA + 解码 网线直连方案
  15. Android-常用基本控件
  16. 大数据 排错日记0004——Unable to check if JNs are ready for formatting
  17. AutoCAD .Net 创建直线Line
  18. Uber Thomas 论文整理
  19. 顶!Python 与 Excel 终于在一起了
  20. Java+MySQL基于SSM的二手玩具交换网站

热门文章

  1. 【Linux】一步一步学Linux——tail命令(42)
  2. Spring Boot WebMagic 入库时 mapper注入提示空指针,以及正确的操作
  3. LeetCode4. Median of Two Sorted Arrays(二分法)
  4. 剑指offer-求二叉树深度
  5. 华软linux虚拟机密码,Linux_账户和组管理
  6. RegEnumValue枚举注册表值小记
  7. 简单常用滤波算法C语言实现
  8. 第二章 PX4-RCS启动文件解析
  9. HDU - Dogs' Candies
  10. A-ID and password