使用工厂模式与泛型对三层架构的每一层进行解耦
我们都知道在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对象的增删改查的具体实现方法(方法内容略):
![](/assets/blank.gif)
![](/assets/blank.gif)
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接口中去:
![](/assets/blank.gif)
![](/assets/blank.gif)
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中的代码如下:
![](/assets/blank.gif)
![](/assets/blank.gif)
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层的实现类就不需要直接创建对象,直接使用工厂模式加泛型即可,如下代码所示:
![](/assets/blank.gif)
![](/assets/blank.gif)
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
使用工厂模式与泛型对三层架构的每一层进行解耦相关推荐
- 桥接模式的应用之三层架构中的业务逻辑层(BLL)与数据访问层(DAL)的解耦
各层的作用 ①用户界面层:只负责显示和采集用户操作. ②业务逻辑层:负责UI和DAL层之间的数据交换,是系统架构中体现核心价值的部分.它关注点主要集中在业务规则的制定.业务流程的实现和业务需求的有关系 ...
- 抽象工厂模式升级版————泛型化实现
引言 今天回看之前总结的抽象工厂模式的实现<Java常用设计模式----抽象工厂模式>,聚焦于抽象工厂模式的缺点,试着改进了一下. 回顾一下抽象工厂模式的缺点: 在添加新的产品类型时,难以 ...
- 阿里为什么建议给MVC三层架构多加一层Manager层?
MVC三层架构 我们在刚刚成为程序员的时候,就会被前辈们 "教育" 说系统的设计要遵循 MVC(Model-View-Controller)架构.它将整体的系统分成了 Model( ...
- java框架三层架构是_MVC框架模式和Javaweb经典三层架构
一.MVC设计模式 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Co ...
- JAVA 工厂模式与泛型之趣味奶茶店
一.趣味咖啡厅的开张 作为拆二代的我,决定不再继续挥霍,想搞搞投资,准备开一家奶茶店... 由于SpringBoot非常便捷与火爆,所以奶茶店采用SpringBoot搭建. 二.创建订单对象 首先,忽 ...
- 三层架构之抽象工厂加反射mdash;mdash;实现数据库转换
在做系统的时候有意识的用到了抽象工厂这个设计模式,主要解决的是数据库更换的问题. 下面就以简单的登录来逐步的分析一下这个模式. 经典的三层架构 数据库如下 1. 一般的数据库连接方式 界面层 ...
- java ssh三层架构_SSH和三层架构的MVC模式的对应关系
1.MVC(Model-View-Controller)设计模式: 首先让我们了解下MVC(Model-View-Controller)的概念: MVC全名是Model View Controller ...
- MVC模式与三层架构的区别
MVC模式与三层架构的区别 原文地址:http://www.cnblogs.com/yourshj/p/5197310.html 之前总是混淆MVC表现模式和三层架构模式,为此记录下. 三层架构和MV ...
- 三层架构和MVC模式
1.三层架构 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了" ...
最新文章
- 网页编程的过程中,怎样让改变标签的属性
- 大地图开发管理:《巫师3》Umbra遮挡剔除技术
- 一脸懵逼学习基于CentOs的Hadoop集群安装与配置(三台机器跑集群)
- Spark配置属性详解
- linux标准IO实验,Linux系统编程(第三篇) 标准IO.pdf
- ASP.NET页面与IIS底层交互和工作原理详解(一)
- SRM 515 DIV1 550pt
- LeetCode Array 最长回文子串-数组和string题目
- Beini FeedingBottle[小巧的无线密码破解系统]
- R语言画图教程之盒形图
- js实现搜索历史记录功能
- 宠物收养所[Treap]
- uestc 1593 老司机破阵(线段树 or multiset)
- (转)DEDECMS模板原理、模板标签学习 - .Little Hann
- EtherCAT和CANopen之间有什么关系?
- Linux之find 命令
- 啃完这些资料,我拿到了腾讯,爱奇艺,Kotlin从入门到进阶实战
- 德温特专利数据的爬取(selenium\xpath\contains解决了输入框ID老是动态改变的问题)
- 宽刈幅干涉高度计SWOT(Surface Water and Ocean Topography)卫星进展(待完善)
- Xilinx DDR3 —— MIG IP核的读写仿真(APP接口)
热门文章
- 【STM32】FreeRTOS列表应用示例
- 【Linux系统编程】进程同步与互斥:System V 信号量
- 【Ubuntu】ubuntu物理机安装方法:U盘安装
- 计算机图形学画圆和直线代码,计算机图形学作业(中点法画直线和八分画圆法).doc...
- 小程序 wx.getBackgroundAudioManager() 手机黑屏后,让控制音频停止
- mac m1下编译spring框架
- set和vector
- python 之 linecache 用法记录
- python3 的windows下文件操作注意问题
- C++ Primer这本书怎么样?