当前位置: 首页 > 编程日记 > 正文

泛型在三层中的应用

一说到三层架构,我想大家都了解,这里就简单说下,三层架构一般包含:UI层、DAL层、BLL层,其中每层由Model实体类来传递,所以Model也算是三层架构之一了,例外为了数据库的迁移或者更OO点,DAL层就衍生出了IDAL接口。Model就是简单的对应数据库里面的类,DAL层就是主要操作数据库的方法了,BLL这个就看业务了。而DAL层大部分的方法都是差不多,无非就是几个Insert,Update,Delete,Select。

      再来说下泛型,这个是2.0才开始有的,算是2.0中一个非常重要的技术了,关于泛型有什么好处优点就不说了,网上一大堆,其实说了也没有什么用,大家在实践中运用了就知道,我觉得泛型一个最核心的地方就是,泛型封装了类型,把类型的定义延迟到了客户端,泛型又像一个类型的模板,只要你定义了一个泛型类,就相当于定义了N个类,每个类的类型不一样而已。

      上面我们说了,三层架构中的DAL层一般包括Insert,Update,Delete,Select这几种了,那么在泛型还没有到来之前,我们的程序员兄弟一般是怎么做的,首先为每个实体定义一个DAL接口,比如有个User这个实体对象,那么就有一个IUserDAL这个接口以及UserDAL这个实现类,如果有N个实体,那么差不多就需要N个接口和实现类了,而这些接口中的Insert,Update,Delete,Select的方法签名都是类似的,唯一的不同就是方法参数和返回值的类型了,我们来看下基本的接口定义

    

View Code
1     public interface IUserDAL
2     {
3         int Insert(User model);
4         int Update(User model);
5         int Delete(int id);
6         User GetModel(int id);
7         DataTable GetList();
8     }

       那么在一个项目中,像这样的接口定义到处可见,大部分是重复的写法,虽然我们有任劳任怨的代码生成工具为我们效劳,但是从设计角度或者站在新技术的角度看,这些代码就显得很不优雅,很不爽了,我想你的感觉也是这样吧,呵呵O(∩_∩)O~。

       当泛型来临时,我们终于可以不看到那么多的重复接口的定义了,终于可以喘一口气了,那么泛型又是怎么实现的呢,在实现之前我们回头看下我们没有泛型的IUserDAL的定义,其中Insert,Update方法就一个User参数,类似的其他接口也就一个参数,只是类型不是User了,可能是Order,或者其他的,在来看下GetModel返回值类型是User,GetList也是一样的,只是这里我们用DataTable这个万能的类型来代替了,但是大家都知道DataTable这个类型臃肿又是弱类型的,在UI层调用的时候又不知道这个DataTable里面到底有什么字段,这个就在开发期带来一定的麻烦。

      泛型的实现终于上场了,其实很简单,不就是一对尖括号吗,是的,只要在IUserDAL后面加对尖括号,里面用一个字符代替类型就可以了,哦,对了还要加个泛型约束呢,就是一个where,也就是说,这个泛型的类型只能是引用的类型,不能是值类型,难道你的Model是一个值类型??不可能吧,反正我是不信。那么这个泛型接口的定义就是:

   

View Code
1     public interface IDAL<T> where T : class
2     {
3         int Insert(T model);
4         int Update(T model);
5         int Delete(int id);
6         T GetModel(int id);
7         IList<T> GetList();
8     }

      哦,原来那么简单就是加个T把之前的User类型给【换了】就可以啦,我怎么没有想到呢,呜呜,那么在UserDAL这个继承类中就可以明确定义那个泛型的类型了,因为我这个类就是用来实现User这个实体类的(或者说数据库的表吧),这里,UserDAL我们就叫IUserDAL的客户端了。代码如下:

    

View Code
 1     public class UserDAL : IDAL<User>
 2     {
 3         #region IDAL<User> 成员
 4
 5         public int Insert(User model)
 6         {
 7             //coding
 8         }
 9
10         public int Update(User model)
11         {
12             //coding
13         }
14
15         public int Delete(object id)
16         {
17             //coding
18         }
19
20         public User GetModel(object id)
21         {
22             //coding
23         }
24
25         public IList<User> GetList()
26         {
27             //coding
28         }
29
30         #endregion
31     }       好了,我们解放了DAL和IDAL,那么BLL层可以用泛型吗,当然可以。

       我们先来说下,不用泛型的BLL层的实现,这里不考虑BLL的业务的话,那么BLL就是单纯的调用DAL的相关数据库操作方法,也就是那个IUserDAL接口定义的方法了,一般的UserBLL代码如下:

     

View Code
 1     public class UserBLL
 2     {
 3         private IUserDAL dal = new UserDAL();
 4
 5         public int Insert(User model)
 6         {
 7             return dal.Insert(model);
 8         }
 9
10         public int Update(User model)
11         {
12             return dal.Update(model);
13         }
14         public int Delete(int id)
15         {
16             return dal.Delete(id);
17         }
18         public T GetModel(int id)
19         {
20             return dal.GetModel(id);
21         }
22         public DataTable GetList()
23         {
24             return dal.GetList();
25         }
26     }

       我想这个是最简单的BLL代码了,而且大部分小的项目这样就已经够了,因为没有什么业务嘛,但是如果想这样的代码每个BLL都这样谢,一个项目几十个上百个也这样写真的会累死人的,代码工具虽然可以解决,但是当我们看到那么多的重复代码,相似的代码,真的很心痛,难道你不觉得心痛,如果你不觉得或者也不想去改的话或者以后还是那样写重复的代码,用代码工具帮做的话,我想你的code能力也不会怎么提高,废话一下。

      那么用泛型的话,我们就可以为所有的BLL定义一个基类,其他类只要继承下,稍微的根据业务的不同增加点业务代码就可以,甚至都可以不用继承了,我们先看代码的实现吧,搞这行代码才是最好说话的,请看下面代码:

     

View Code
 1     public class BaseBLL<T, D>
 2         where T : class
 3         where D : IDAL<T>,new ()
 4     {
 5         private D dal = new D();
 6
 7         public virtual int Insert(T model)
 8         {
 9             return dal.Insert(model);
10         }
11
12         public virtual int Update(T model)
13         {
14             return dal.Update(model);
15         }
16         public virtual int Delete(object id)
17         {
18             return dal.Delete(id);
19         }
20         public virtual T GetModel(object id)
21         {
22             return dal.GetModel(id);
23         }
24         public virtual IList<T> GetList()
25         {
26             return dal.GetList(model);
27         }
28     }

        这个也简单把,也就是把实体类换为T,把IDAL接口换为D,并定义D这个类型的约束,也就是说我的这个D一定是一个实现了IDAL<T>这个接口的,而IDAL尖括号里面的T就是BaseBLL里面的T,看到这里,相信大家都应该明白了,如果你想实现UserBLL,就可以继承BaseBLL这个基类,这里为什么把BaseBLL中的方法定义为virtual呢,原因很简单的,因为你的BLL层的其他类不可能就没有业务,不可能就是简单的调用DAL方法吧,其他的BLL类就可以根据业务去override相关的方法了,UserBLL相应代码如下:

    

View Code
1     public class UserBLL : BaseBLL<User, UserDAL>
2     {
3       
4     }       如果UserBLL没有任何业务的话,那就不要继承了,在UI直接用BaseBLL这个泛型类就可以,调用也很简单

       BaseBLL<User> dal=new BaseBLL<User>();这样就可以了。

原文引用。

转载于:https://www.cnblogs.com/xiaogelove/archive/2012/03/21/2410276.html

相关文章:

【蓝桥java】进制与整除之尼姆堆

题目&#xff1a; 有3堆硬币&#xff0c;分别是3,4,5 二人轮流取硬币。 每人每次只能从某一堆上取任意数量。 不能弃权。 取到最后一枚硬币的为赢家。 求先取硬币一方有无必胜的招法。 在提供代买前做几条补充&#xff1a; &#xff08;1&#xff09;这里有一个不是很好理解的…

RSA遭骇 Token 换?不换?

RSA SecurID Token召回更换的动作仍然持续进行中&#xff0c;根据外电报导&#xff0c;美国有些企业已经要求更换Token&#xff0c;如花旗集团、美国银行、富国银行、摩根大通、澳盛银行、澳洲西太平洋银行。于此同时&#xff0c;一些竞争供应商也动作频频&#xff0c;例如Safe…

二叉树的镜像(数组,前后 遍历重建二叉树)

题目描述 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。输入描述: 二叉树的镜像定义&#xff1a;源二叉树 8/ \6 10/ \ / \ 5 7 9 11镜像二叉树8/ \10 6/ \ / \11 9 7 5 #include <iostream> #include <cstdio> #include <cstdlib> #in…

tp5实现Redis的简单使用

方法1&#xff1a; Controller <?php namespace app\index\controller;use think\Controller; use think\session\driver\Redis;class Index extends Controller {public function index(){$redis new Redis();if(!$redis->has(str)){var_dump($redis->set(str,this…

Linux下getsockopt/setsockopt 函数说明

【getsockopt/setsockopt系统调用】 功能描述&#xff1a; 获取或者设置与某个套接字关联的选 项。选项可能存在于多层协议中&#xff0c;它们总会出现在最上面的套接字层。当操作套接字选项时&#xff0c;选项位于的层和选项的名称必须给出。为了操作套接字层的选项…

【蓝桥java】进制与整除之最大公约数 最小公倍数

补充&#xff1a; &#xff08;1&#xff09;欧几里得定理&#xff08;辗转相除法&#xff09;&#xff1a;A和B的最大公约数 B和A%B 的最大公约数 &#xff08;2&#xff09;将两个数乘起来再除以最大公约数就是最小公倍数 package cn.zzunit.jnvi;/***寻找最大公约数* autho…

学习C#要养成的好习惯

1. 避免将多个类放在一个文件里面。2. 一个文件应该只有一个命名空间&#xff0c;避免将多个命名空间放在同一个文件里面。3. 一个文件最好不要超过500行的代码&#xff08;不包括机器产生的代码&#xff09;。4. 一个方法的代码长度最好不要超过25行。5. 避免方法中有超过5个参…

3.1、final、finally、 finalize

final 可以用来修饰类、方法、变量&#xff0c;分别有不同的意义&#xff0c;final 修饰的 class 代表不可以继承扩展&#xff0c;final 的变量是不可以修改的&#xff0c;而 final 的方法也是不可以重写的&#xff08;override&#xff09;。 finally 则是 Java 保证重点代码一…

Android模拟器学framework和driver之传感器篇1(linux sensor driver)

对于android模拟器开发环境的搭建这里我就不多说了&#xff0c;网上google下一大堆&#xff0c;还有就是android 模拟器的kernel使用的是goldfish的kernel&#xff0c;可以使用git得到源码&#xff0c;然后就可以编译了&#xff0c;大家还是可以参考罗老师的博客。。。 在这里我…

【java】Lombok的使用

介绍&#xff1a;lombok在编译entity文件时自动生成get set toString hashCode等方法&#xff0c;这样方法生成就不用写在代码里了&#xff0c;可以简化代码。 使用方法&#xff1a; 一、在pom文件里引入lombok的依赖 代码实现&#xff1a; <dependency><groupId&g…

自己开发开源jquery插件--给jquery.treeview加上checkbox

很多时候需要把树状的数据显示除来&#xff0c;比如分类&#xff0c;中国省份、城市信息&#xff0c;等&#xff0c;因此这方面的javascript插件也有很多.比如性能优异的jquery.treeview和国人开发的功能强大的zTree. 我最近在一个项目中用到了jquery.treeview&#xff0c;但是…

SQL Server 2000安装时不出现安装界面,进程中存在解决

在XP和Server 2003系统中安装SQL Server 2000过程中&#xff0c;点击安装后&#xff0c;一直不出现安装界面&#xff0c;查看进程中也有&#xff0c;一直无反应。 解决办法&#xff1a; 首先重新启动机器&#xff0c;或者任务管理器里面结束2个sql进程 1. 在 SQLServer 安装向导…

Apache2.4部署python3.6+django2.0项目

一、安装apache Apache是非常有名的web服务器软件&#xff0c;如果想让我们web项目运行几乎离不开它。 Apache官方网站&#xff1a;http://httpd.apache.org/ 根据自己的环境&#xff0c;选择相应的版本进行下载。apache 官网没有windows 64位版本&#xff0c;可以通过下面的链…

我是如何有效的避免测试漏测?

漏测&#xff0c;指在产品缺陷在测试过程中没有被发现&#xff08;尤其是测试环境可以重现的缺陷&#xff09;&#xff0c;而是在版本发布后或者在用户使用后发现并反馈回来的缺陷。可以说&#xff0c;漏测的问题是测试管理者最头痛的问题。因为出现漏测&#xff0c;一来给客户…

总结是学习最好的方式(转)

总结是学习最好的方式 最近一直想总结来华为公司这3个多月自己有什么收获&#xff0c;但又想不明白自己收获了什么&#xff1f;说技术吧&#xff0c;也谈不上有多大的提高&#xff1b;说人际交流&#xff0c;也许还有些退步&#xff1b;说薪资存款吧&#xff0c;哎不谈了。想着…

【转载】JUnit各个注解的含义

转自&#xff1a;https://blog.csdn.net/weixin_38500014/article/details/84393775

silverlight、wpf中 dispatcher和timer区别

相同点&#xff1a;都是定时执行任务的计时器&#xff0c;都可以使用。 不同点&#xff1a;Timer运行在非UI 线程&#xff0c;如果Timer需要更新UI的时候&#xff0c;需要调用 Invoke或者 BeginInvoke DispatcherTimer运行在UI 线程&#xff0c;处理的 Dispatcher 队列中的计时…

web开发基础

web开发:所谓web开发就是基于浏览器服务器的开发下面将web开发基础知识作个总结:1.http协议:是建立在TCP协议上的,基于请求响应的模型2.http请求:面试题:说说get与post的区别a.传递数据量:get只能传递1kb以下的数据,post可以传递大数据b.安全性:get请求,如果携带参数,参数会直接…

让ubuntu下的eclipse支持GBK编码

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://leaze.blog.51cto.com/83088/195584今天&#xff0c;把windows下的工程导入到了Linux下eclipse中&#xff0c;由于以前的工程代码&#x…

Session,ViewState用法

Session,ViewState用法基本理论&#xff1a; session值是保存在服务器内存上,那么,可以肯定,大量的使用session将导致服务器负担加重. 而viewstate由于只是将数据存入到页面隐藏控件里,不再占用服务器资源,因此, 我们可以将一些需要服务器"记住"的变量和对象保存到vi…

【HTML】记录自己丢人过程:文本换行缩进都不会

问题描述&#xff1a; html文本想实现换行和缩进&#xff0c;最后气到摔鼠标 换行 实现代码&#xff1a; <br> 直接在文本后加个换行标签即可 缩进 实现代码&#xff1a; style"text-indent: 2em;" 注意&#xff1a;这个属性放到p标签中或者div标签中都…

CentOS5.6系统下mysql5安装

我的系统是CentOS5.6 建议大家完全安装&#xff0c;以免安装时缺少相关的编译器等等。 一、安装mysql&#xff08;mysql-5.1.50.tar.gz&#xff09; # tar zxf mysql-5.1.50.tar.gz # cd mysql-5.1.50 #./configure --prefix/usr/local/mysql --sysconfdir/etc --localstated…

CentOS 6.9/7通过yum安装指定版本的JDK/Maven

说明&#xff1a;通过yum好处其实很多&#xff0c;环境变量不用配置&#xff0c;配置文件放在大家都熟悉的地方&#xff0c;通过rpm -ql xxx可以知道全部文件的地方等等。 一、安装JDK&#xff08;Oracle JDK 1.8&#xff09; # wget --no-check-certificate --no-cookies --he…

2019牛客全国多校训练三 题解

A Gragh Games Unsolved. B Crazy Binary String 题解&#xff1a;水题&#xff0c;子序列只要统计0和1数量&#xff0c;取最小值然后乘2就是答案&#xff1b; 对于子串&#xff1a;先记录0和1 前缀和的差值&#xff0c;然后找差值相等的距离最远的两个位置即可&#xff1b; 参…

【硬件基础】有源蜂鸣器与无源蜂鸣器

辨别方法 外观&#xff1a; 无源蜂鸣器: 有源蜂鸣器&#xff1a; 注&#xff1a;可以看到底部有绿色电路板的是无源蜂鸣器&#xff0c;底部是黑胶的为有源蜂鸣器 万用表电阻档检测 无源蜂鸣器&#xff1a;发出咔、咔声的且电阻只有8Ω&#xff08;或16Ω&#xff09;。 有源…

hdu 1272 小希的迷宫

Problem Description上次Gardon的迷宫城堡小希玩了很久&#xff08;见Problem B&#xff09;&#xff0c;现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样&#xff0c;首先她认为所有的通道都应该是双向连通的&#xff0c;就是说如果有一个通道连通了房间A和B…

技术还是商业重要

在中国IT业创业听得最多的就是&#xff0c;技术不重要&#xff0c;商业和关系才是最重要的。 到了硅谷之后&#xff0c;发现技术气氛十分浓&#xff0c;甚至有朋友说大陆创业比较容易是因为硅谷与之相比&#xff0c;硅谷太注重技术了。 可是慢慢发现其实在硅谷&#xff0c;商业…

bzoj1036: [ZJOI2008]树的统计Count 树链剖分

一棵树上有n个节点&#xff0c;编号分别为1到n&#xff0c;每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作&#xff1a; I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的…

cocos lua 加密方案

cocos2d使用的是luajit&#xff0c;lua原生编译出来的bytecode和luajit是不兼容的&#xff0c;所以直接用luac法编译出来的bytecode脚本无法在cocos2d中使用。 目前所指的解决方案有2个&#xff1a; A.luajit加密&#xff1a; 1、官网下载luajit&#xff08;http://luajit.org/…

VS2010创建ATL类时需要手动填写ProgID

在新建ATL类的时候VS2010默认是不填写ProgID的&#xff1a; 所以默认创建的类生成的rgs文件中只有NoRemove CLSID这一栏&#xff0c;导致在JS中使用new ActivexObject(“LibName.ClassName”)失败。如果想用ActivexObject创建类的话就必须填写ProgID。转载于:https://www.cnblo…