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

  我们都知道在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 }

  将该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 }

  如果没有使用工厂模式,那么因为没什么好的方法,所以只能在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 }

  这样在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 }

分析:

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

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

时间: 2024-10-13 15:58:00

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

asp.net mvc中自行搭建实现工厂模式的spring.net+三层架构 (15-4-20)

在之前的文章中,我们已经搭好了三层框架,通过调用业务层的子接口得到实例化的业务子类,通过业务子类来调用数据访问层子接口,由子接口来实例化数据访问层子类.这里我们需要明确把框架搭这么复杂的原因是遵循了设计模式中的开闭原则:对扩展开放,对修改关闭. 搭好了框架之后,我们发现这框架并不完善:实例化对象还需要手动实现,并不能实现将对象的实例化托管.所以我们决定引入spring.net框架,它的IOC模块(依赖注入),将帮我们来完成对象的创建,管理. 1.首先我们需要在项目中引用spring.core.d

asp.net mvc中自行搭建实现工厂模式的spring.net+三层架构(更新)

首先附上本人托管在Github上的项目https://github.com/lichaojacobs/Tomato 接下来的三层结构都包含了父接口,子接口,父类,子类部分 1.编写数据访问层 数据访问层是对数据库的增删改查的操作.首先我们在数据访问层的父接口声明一些通用的对数据库统一处理的方法: 然后是业务层子接口(对应于你的数据实体模型中的Model,下面是我的项目中的Model,仅供参考),让它继承自业务层父接口 写完接口,接下来编写父接口的实现父类BaseDAL.cs 注意,在这里是通过一

架构和模式的区别:三层架构和MVC在应用开发中的位置

架构是系统层面的,可以是多层架构,也可以是事件驱动架构,也可以是微服务架构. 模式是GUI应用的一种职责分离设计. 三层架构(包含多层架构)和 MVC模式(包含MVP, MVVM) 没什么关系,它们不在同一个维度上. 三层架构是从整个应用程序架构的角度来分为DAL(数据访问层).BLL(业务逻辑层).WEB层(界面层)各司其职,意在职责分离:三层是为了解决整个应用程序中各个业务操作过程中不同阶段的代码封装的问题,为了使程序员更加专注的处理某阶段的业务逻辑:并且三层只是多层架构中的一种情况,完全可

MVC框架模式和Javaweb经典三层架构

一.MVC设计模式 1.MVC的概念 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),即为MVC.它是一种软件设计的典范,最早为Trygve Reenskaug提出,为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式. 2.MVC的详解 虽然MVC并不是Java当中独有的,但是现在几乎所有的B/S的架构都

MVC模式与三层架构的区别

之前总是混淆MVC表现模式和三层架构模式,为此记录下. 三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层) 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了“高内聚,低耦合”的思想. 1.表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得.    2.业务逻辑层(BLL):针对具体问题的操作,也可

浅析MVC模式与三层架构的区别01

三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层)三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了“高内聚,低耦合”的思想.1.表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得.   2.业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理.   3.数据访问层

三层架构和MVC模式

1.三层架构 三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了"高内聚,低耦合"的思想. 1.表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得. 2.业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理. 3.数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添.删除.修改.更新.

浅析MVC模式与三层架构的区别

三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层)三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了“高内聚,低耦合”的思想.1.表现层(UI):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得.   2.业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理.   3.数据访问层

C#三层架构详细解剖

深入浅出C#三层架构(转) 本文用一个示例来介绍如何建设一个三层架构的项目,并说明项目中各个文件所处的层次与作用.写本文的目的,不是为了说明自己的这个方法有多对,而是希望给那些初学三层架构却不知从何入手的朋友提供一点帮助.因为网上的文章,大多是注重理论的介绍,而忽略了具体的实践应用,或者有示例但讲得不透彻.导致看了之后,理论上又学习了一遍,但还是不知道代码怎么写.所以想从这个方面入手写一下,让从来没做过三层架构的初学者也能照猫画虎,写出代码来.文中的代码是伪代码,仅用来阐明思路.    正文: