浅谈三层架构 通过这个,+Java开发模式经验。终于相通了,动软到底是为什么这么做...
浅谈三层架构 收藏
自己理解的原理
http://www.cnblogs.com/mahaisong/archive/2011/05/12/2044665.html
浅谈三层架构 通过这个,+Java开发模式经验。终于相通了,动软到底是为什么这么做。
,NET开发两个项目了。半年了。一直没搞懂。为什么。net的三层是这样的。原来今天这里的三层是这样的啊?
BLL 做业务逻辑。 DAL 做 数据操纵。 第三次是 界面层(codeBehind).
这就是三层。和JAVA没什么不同。只不过。我一直在纠结。为什么 MVC 要这样分。其实我错了。MVC 是最基础,然后再分成三层。为什么这么说那。
MVC。M(Model)-V(View)-C(Control)。 我们一般做操作就把COntorl 做成一个操作的封装就O了。
而如果开辟大局观的面向对象的话。 Model是数据的对象核心。 而操作的核心 因为 面向对象的 思想。进行各种接口化 (自动选择对应的数据库。封装的概念。) 这样就把面向对象 超越编码 提高到了架构上了。
因此。这里它还增加了一个工厂模式。
我这里分析一下。 Bll 做业务逻辑。
private readonly IActivityComment dal=DataAccess.CreateActivityComment();
利用 接口
public sealed class DataAccess
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];
//不使用缓存
private static object CreateObjectNoCache(string AssemblyPath, string classNamespace)
{
try
{
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch//(System.Exception ex)
{
//string str=ex.Message;// 记录错误日志
return null;
}
}
//使用缓存
/// <summary>
/// 创建ActivityComment数据层接口
/// </summary>
public static database.IDAL.IActivityComment CreateActivityComment()
{
string ClassNamespace = AssemblyPath + ".ActivityComment";
object objType = CreateObject(AssemblyPath, ClassNamespace);
return (database.IDAL.IActivityComment)objType;
}
利用反射,反射到SQLSERVERDAL,得到数据,封装到接口中。 而Bll中的方法,和IDAL的方法是对应的关系(大多数)。因为为了封装,就利用BLL中的方法调用实际的IDAL中的方法。(反射,委托,事件,在三个的存在+更高层次的面向对象是 真正难理解的地方。)
每天思考深一点三层。终身受益。
三层架构并不是MVC,MVC是一个很早就有的经典的程序设计模式,M-V-C分为三层,M(Model)-V(View)-C(Control)。而web开发中的三层架构是指:数据访问层(DAL-DatabaseAccessLayer),业务逻辑层(BLL-BusinessLoginLayer),以及用户界面层(UI-UserInterface,实际就是网页后台的具体调用BLL层)。这个是基本概念。曾经我以为三层架构就是在AppCode中,分为三个大类与若干小类,各司其职。在经过一番洗礼后,才发觉多么的无知。
首先AppCode中,放的是通用类,如数据库通用类,实现数据库连接,基本的SqlCommand创建,自定义CRUD的方法等,与三层架构毫无关系,就是常用的开发模式中存放类(Class)的文件夹。
其次,当使用三层架构时,一定是在大项目中,因为三层架构的目的是提高项目的松散性和降低项目的耦合度,使之更容易扩展或者维护。小项目使用了三层架构,由于过度的在意分层而导致了项目的复杂度增加。
创建三层架构的应用程序。我们必须对这三层分别创建不同的类库(ClassLibrary),而不是普通的类(Class)。我们对于任何一个模块或者功能进行OOP,把它扩展为对象(面向对象的思想就是:将所操作的目标当成一个对象,对它进行的操作,将由对象自己的方法进行,而非外界传参。譬如注册用户,用面向过程的方法事先,就是:public static bool Register(string userName, string userPwd)。若用OO的思想,我们不可将账号密码作为参数传入,而是将用户作为一个对象,这个对象具有private _userName,和private _userPwd的属性。在注册时,用构造函数初始化一个新的对象,User one = new User(userName,userPwd),使之在初始化后具有这两个字段的值。然后调用User类中的public static bool Register()方法(注意这个方法是不进行传参的),而在这个Register方法中,使用对象的_userName和_userPwd属性进行注册。),那么,我们在这个对象中的任何操作都将以该对象的方法(函数)实现。
在进行三层分类时,这样新建类库。
1.文件->新建项目->其他项目类型->空白解决方案。
2.在右侧的“资源管理器”中,选中当前解决方案,右键添加->新建项目->类库(ClassLibrary),分别创建BLL,DAL,UL类库。(若添加后看不到解决方案则在菜单->工具->选项->项目和解决方案->总是显示解决方案)。
3.右键,向解决方案中添加一个网站(新网站或者现有网站)。
4.根据需求删除或者保留默认添加项(默认的class1.cs或Default.aspx文件)。
这样一个三层架构的网站雏形就搭建好了。因为UI层要被其他两层引用,DAL层要被BLL层引用。所以需要相互添加引用,方法是在类库上点击右键->添加引用->项目->选择其他类库。并且在具体类中引入命名空间(using namespace)。
ps:类库其实就是类的集合,三层架构的目的就是,将同一项目的不同模块都划分为各自的三层,各司其职,将具体实现方法用类写出,添加到该层的类库中,这样,一个网站下的类库就只有三层,每一层中都包含了各个模块相对应层的实现方法。在以后修改或扩展时,在对应层中进行操作就可以了。
一般的项目,涉及最多的就是对数据库的CRUD,DAL层只负责与数据库的交互,BLL层是最重要的一层,他负责将DAL层的的结果呈现给UI层,但是恰恰BLL层的存在似乎有点鸡肋,他起到的仅仅是转发DAL层数据的作用,而具体的逻辑操作是与数据库的交互,应该写在DAL层,这就好像BLL层是在重复DAL层的劳动一样,其实BLL层的作用在于除了调用DAL层访问数据库,还可以进行逻辑判断,当符合的时候,才进行允许进行DAL的操作,或者进行额外的操作(如加密,转换等)。而DAL层可不管这些,他只管进行CRUD的动作。UI层就是操作抽象出来的实体对象,它包含了各种属性。
在这里我说一下。简单三层的架构:WEB,BLL ,DAL做主框架。而MOdel 因为面向对象+每层都用。所以独立出来。和DAL并列。
解密,缓存,数据校验,因为是通用,也单独分离。放在Common类中。而,数据库访问类,因为数据库的多种多样,所以有一个 通用的数据库操作类。叫做DBUtility 独立出来,专门做 数据库访问的,(例如,反射后自动区分是访问EXCEL还是SQL),与Common并列。
DBUtility是对ADO.NET的封装,封装了一些常用的重复的数据库操作。 如微软的SQLHelper。cs 或动软的DBUtility/DbHelperSQL等,为DAL提供访问数据库的辅助工具类。
这样简单三层出来了。 所以有两个文件夹 database 和utility;
database 下有 BLL和 DAL。因为WEB 程序(aspx或jsp)是表示层。所有不放这里。
utility 下有 Common 类和 DBUtility 类。Common 类是通用的辅助工具类。
DBUtility 类是数据访问类。
而WEB 中aspx页面Using 对应的 database 中的类。是因为。引用了。才能用啊。 而引用程序集。可以在 “引用”--“右键” 添加引用中做。
如果想再了解。请见下一篇转载的大话简单三层。
一个三层架构的小例子:注册新用户。
先写模块的实体类,是数据库中表的抽象,假设数据库中注册信息只有账号,密码两个字段。那么抽象到实体类就是这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Entity
{
class UserInfo
{
public string UserName { get; set; } //C#3.0中属性构造器的新写法;
public string UserPwd { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Entity
{
class UserInfo
{
public string UserName { get; set; } //C#3.0中属性构造器的新写法;
public string UserPwd { get; set; }
}
}
再写DAL层:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using Entity; //这里添加对Entity实体类的引用; namespace DAL { public class UserDAL { //在该类中,为了方便,一般会构造一个DataBaseFactory,方便进行代码的操作。所以以下代码仅为逻辑实现,不代表代码正确。 public bool AddUser(UserInfo uInfo) //这里将实体类作为参数传入; { string sqlStr="INSERT INTO UserInfo(Name,Pwd) VALUES(@name,@pwd)"; SqlCommand cmd=new SqlCommand(sqlStr); cmd.Parameters.Clear(); cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = uInfo.UserName; //调用实体类的属性 cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = uInfo.UserPwd; return Convert.ToInt32(cmd.ExecuteNonQuery()) > 0 ? true : false; } public DataTable GetUserInfo(string name) //根据用户名获得用户的具体信息 { string sqlStr="SELECT * FROM UserInfo WHERE Name=@name"; SqlCommand cmd=new SqlCommand(sqlStr); cmd.Parameters.Clear(); cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = name; SqlDataAdapter sda = new SqlDataAdapter(cmd); DataSet ds=new DataSet(); sda.Fill(ds,"UserInfo"); return ds.Tables["UserInfo"]; } } } using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Entity; //这里添加对Entity实体类的引用;
namespace DAL
{
public class UserDAL
{
//在该类中,为了方便,一般会构造一个DataBaseFactory,方便进行代码的操作。所以以下代码仅为逻辑实现,不代表代码正确。
public bool AddUser(UserInfo uInfo) //这里将实体类作为参数传入;
{
string sqlStr="INSERT INTO UserInfo(Name,Pwd) VALUES(@name,@pwd)";
SqlCommand cmd=new SqlCommand(sqlStr);
cmd.Parameters.Clear();
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = uInfo.UserName; //调用实体类的属性
cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = uInfo.UserPwd;
return Convert.ToInt32(cmd.ExecuteNonQuery()) > 0 ? true : false;
}
public DataTable GetUserInfo(string name) //根据用户名获得用户的具体信息
{
string sqlStr="SELECT * FROM UserInfo WHERE Name=@name";
SqlCommand cmd=new SqlCommand(sqlStr);
cmd.Parameters.Clear();
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = name;
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds=new DataSet();
sda.Fill(ds,"UserInfo");
return ds.Tables["UserInfo"];
}
}
}
再写BLL层:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Entity; //添加对Entity类库的引用
using DAL; //添加对DAL类库的引用
namespace BLL
{
public class UserBLL
{
public static bool AddUser(UserInfo uInfo) //BLL层的方法多为静态方法,DAL层也可以为静态方法。
{
UserDAL uDal = new UserDAL();
DataTable dTable = uDal.GetUserInfo(uInfo.UserName);
if (dTable.Rows.Count > 0) //这里对注册用户有一个判断,从DAL层中先通过注册名获得用户的具体信息,若可以获得则证明该用户名已被注册,返回false;
return false;
else
return uDal.AddUser(uInfo);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Entity; //添加对Entity类库的引用
using DAL; //添加对DAL类库的引用
namespace BLL
{
public class UserBLL
{
public static bool AddUser(UserInfo uInfo) //BLL层的方法多为静态方法,DAL层也可以为静态方法。
{
UserDAL uDal = new UserDAL();
DataTable dTable = uDal.GetUserInfo(uInfo.UserName);
if (dTable.Rows.Count > 0) //这里对注册用户有一个判断,从DAL层中先通过注册名获得用户的具体信息,若可以获得则证明该用户名已被注册,返回false;
return false;
else
return uDal.AddUser(uInfo);
}
}
}
最后构建UI层代码,即我们的aspx.cs页面代码,该层应该直接调用BLL层的方法。该页面引用BLL和Entity的命名空间,并向Button控件注册事件:
protected void btnRegister_OnClick(object sender, EventArgs e)
{
UserInfo uInfo = new UserInfo(textUserName.text, textUserPwd.text);
if (UserBLL.AddUser(uInfo))
Response.Write("注册成功!");
else
Response.Write("注册失败!");
}
protected void btnRegister_OnClick(object sender, EventArgs e)
{
UserInfo uInfo = new UserInfo(textUserName.text, textUserPwd.text);
if (UserBLL.AddUser(uInfo))
Response.Write("注册成功!");
else
Response.Write("注册失败!");
}
这样一个小的三层架构程序就出来了。
这个程序中,操作的实体为UserInfo表的抽象。在DAL层进行了AddUser()的方法,在BLL层也进行了AddUser()的方法,唯一的区别是BLL层做了逻辑判断,如果用户名存在,则注册失败。
三层架构的特点:
1.数据库访问层(DAL)仅提供对数据库的CRUD操作,而不管操作后的结果,也不管逻辑过程(譬如同名用户,不合法用户名)。
2.业务逻辑层(BLL)不会直接与数据库交互,他与数据库的交互是通过DAL提供的方法。在调用这些方法前,要加入自己的逻辑判断或者业务处理。另外业务逻辑层(BLL)还有可能不会去调用DAL层的方法,而是进行其他业务处理。
3.用户界面层(UI)层是不会调用DAL层的,他只调用BLL层提供的方法,再由BLL层自己决定是否继续调用DAL层。
这个例子可以看出三层架构的优点就是结构清晰,容易扩展与维护。缺点就是,复杂。仅仅一个注册用户,就这么麻烦,所以对于小项目来说,费这么大劲换取一个相对较清晰的分层结构是不划算的。
转载请注明出处:csdn-mark
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mark4ever/archive/2011/04/05/6302353.aspx 有一部分,也是我自己添的哈。嘿嘿
浅谈三层架构 通过这个,+Java开发模式经验。终于相通了,动软到底是为什么这么做...相关推荐
- 浅谈三层架构、MVC之间的关系
什么是三层架构? 各个层的作用 实体层的作用 什么是MVC? 概念 职能 设计模式 三层架构.MVC之间的关系 关系示意图 三层的优缺点 MVC的优缺点 什么是三层架构? 三层架构(3-tier ar ...
- 浅谈三层架构中的实体类(C#)
最近因为三层架构中的实体类,引发了不少小问题,下面列举一下,谈谈自己的感想. 本文所指的实体类仅限于三层中的实体类,即数据库表的映射. 一.为什么要用实体类? | 使程序简洁易懂,便于维护. | ...
- Java架构师成长之道之浅谈计算机系统架构
Java架构师成长之道之浅谈计算机系统架构 Java架构师成长之旅 1.1 信息技术发展趋势 目前信息技术主要经历了互联网.移动互联网以及以大数据.云计算.人工智能和区块链为代表的新兴技术三个阶段.而 ...
- 浅谈“三层结构”原理与用意(转帖)
浅谈"三层结构"原理与用意 序 在刚刚步入"多层结构"Web应用程序开发的时候,我阅读过几篇关于"asp.net三层结构开发"的文章.但其多 ...
- 浅谈分布式架构搭建-理论知识
浅谈分布式架构搭建 基础 理念 技术选型 后端技术设计 总体架构设计 关键案例设计 架构师搭建架一般优先考虑的是安全性.稳定性.高吞吐量.哈哈,菜鸟的我让我装个B,回忆一下以前架构搭建 基础 理念 C ...
- 编程浅谈-以一个初出茅庐的Java程序员视角
编者是一个从事Java开发的普通软件攻城狮,迄今为止,粗粗算来不过刚刚进入编程的世界不过两年,但在这两年的光阴里,每当我抬头仰望星空(苦命加班)时脑海里总有这样一个疑问--"什么是编程&qu ...
- 理解各种设计模式原则及区别丨浅谈Nginx中核心设计模式-责任链模式丨C++后端开发丨Linux服务器开发丨web服务器
理解各种设计模式原则及区别丨浅谈Nginx中核心设计模式-责任链模式 1. 开闭.单一职责.里氏替换.接口隔离等设计原则 2. 随处可见的模板方法 3. nginx中核心设计模式 责任链模式 4. 责 ...
- javaweb基本三层架构并使用Eclipse开发Servlet
javaweb基本三层架构并使用Eclipse开发Servlet JAVAEE分层模型 web应用程序基本架构 Domain Object Data Access Object 业务逻辑层 控制器层 ...
- 关于计算机运行管理模式,浅谈学校计算机机房管理及维护运行模式.docx
浅谈学校计算机机房管理及维护运行模式 摘要:计算机辅助教学在学校的教学体系中占有重要地 位,计算机机房是学校教学和学生实践学习的重要学习场 所.合理的机房管理与维护模式,是提高学校教学质量和培 养学生 ...
最新文章
- [Usaco2005 Open]Disease Manangement 疾病管理 BZOJ1688
- python语言句块的标记_Python语言语句块的标记是()
- C#将内容导出到Word到指定模板
- android studio tree,Git 、Sourse Tree 和 Android Studio配置遇到的问题
- Android 添加 *.arr
- 【算法竞赛学习】气象海洋预测-Task5 模型建立之 SA-ConvLSTM
- 如何手撸一个较为完整的RPC框架?
- linux qt创建静态库,QT创建与QT无关的纯C++程序和动态/静态库
- shell 判断文件出现次数
- 用JavaScript实现简单的乘法计算
- VS code Could not establish connection to IP 解决方法
- 集合框架学习笔记(下)
- 【ROS2原理11】C++编程的要点
- 2022-08-22 第六小组 瞒春 学习笔记
- 基于OAuth2的认证
- 【人工智能】大脑传:人类大脑认识发展史
- r5 5600u和r5 4600u参数对比哪个好?
- AndroidRuntimeException: requestFeature() must be called before adding content异常解决办法
- PostgreSQL 查表、所属schema、字段、字段类型、注释等信息
- 关于牛客网代码题 数据读取问题的 小白指南