三层架构
发布日期:2021-06-29 11:15:34 浏览次数:2 分类:技术文章

本文共 4496 字,大约阅读时间需要 14 分钟。

为什么要用三层

  说到三层,先来说一说两层结构。两层结构将界面展示、业务逻辑、数据访问等都写到一起,如果用户需求变化,就需要对整个项目进行大量修改,系统的维护和升级极其不利;而且界面层直接访问数据库,还会有安全隐患。结构如下图所示:

这里写图片描述
  所以基于两层结构的局限性,三层结构就出现了。三层结构符合“高内聚、低耦合”的特点,每个层职责明确。利用分层,降低了层间依赖,使系统的耦合更加松散,从而使系统更加容易维护和复用。
  比如:如果需求有变化,只需要更改相应的业务逻辑层;或者要改变数据库的时候,只需要将原来的数据访问层替换掉或者增加新的就可以了,而不需要牵扯到整个项目。
  三层架构虽好,但是也不是每个项目都必须采用这种结构,三层结构用于比较复杂的大型系统,如果系统比较小,则没必要将问题复杂化。

何为三层

这里写图片描述

三层由显示层(UI)、业务逻辑层(BLL)、数据访问层(DAL)组成。
1.显示层(UI)
  职责:①向用户展示特定的业务数据
     ②采集用户的信息和操作
  原则:用户至上,兼顾简洁

2.业务逻辑层(BLL)

  职责:① 从UI中获取用户指令和数据,执行业务逻辑
     ②从UI中获取用户指令和数据,通过DAL写入数据源
     ③从DAL中获取数据,以供 UI 显示用
  机制:① UI –> BLL –> UI
     ② UI –> BLL –> DAL –> BLL –> UI

3.数据访问层(DAL)

  作用:跟数据源打交道
  职责:①执行对数据的操作(增删改查)

4.数据对象层

  数据对象层包含了项目需要使用的数据对象,用数据对象来传递数据,它避免了各个层的交叉引用。
  一般一个表对应一个数据对象。

引用关系

上图已经展示了它们三者之间的引用关系。UI层–> BLL层 –> DAL层,而它们都引用数据对象层。

代码展示

下面以一个登录的小例子,展示一下三层是如何具体使用的。

UI层:

public partial class Form1 : Form{    public Form1()    {        InitializeComponent();    }    private void btnLogin_Click(object sender, EventArgs e)    {        //获取输入的用户名和密码        string userName = txtUserName.Text.Trim();        string userPassword = txtPassword.Text;        Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();        //调用B层的登录方法,从B层返回user的信息        UserInfo user = mgr.Login(userName, userPassword);        MessageBox.Show("登录用户:" + user.UserName);    }}

BLL层:

public class LoginManager{    public UserInfo Login(string userName,string password)    {        //实例化UserDao        UserDAO uDao = new UserDAO();        //调用UserDao的查询用户方法        UserInfo user = uDao.SelectUser(userName, password);        //如果用户存在,就调用ScoreDao的更新积分方法,给用户加10积分;否则就抛出异常        if (user != null)        {            ScoreDAO sDao = new ScoreDAO();            //调用ScoreDao的更新积分方法            sDao.UpdateScore(userName, 10);            return user;        }        else        {            throw new Exception("登录失败。");        }    }}

DAL层:

public class UserDAO{    ///     /// 查询用户是否存在并返回用户信息    ///     /// 用户名    /// 密码    /// 
public UserInfo SelectUser(string userName,string password) { using (SqlConnection conn = new SqlConnection(DbUtil.ConnString)) { SqlCommand cmd = conn.CreateCommand(); //获取执行的SQL语句 或表名 或存储过程名 cmd.CommandText = @"SELECT ID,UserName,Password,Email FROM USERS WHERE UserName=@UserName AND Password=@Password"; //指示执行的是存储过程还是sql语句,默认执行语句 cmd.CommandType = CommandType.Text; cmd.Parameters.Add(new SqlParameter("@UserName", userName)); cmd.Parameters.Add(new SqlParameter("@Password", password)); conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); UserInfo user = null; while (reader.Read()) { if (user == null) { user = new UserInfo(); } user.ID = reader.GetInt32(0); user.UserName = reader.GetString(1); user.Password = reader.GetString(2); if (!reader.IsDBNull(3)) { user.Email = reader.GetString(3); } } return user; } }}public class ScoreDAO{ /// /// 更新用户积分 /// /// 用户名 /// 要增长的积分 public void UpdateScore(string userName,int value) { using (SqlConnection conn = new SqlConnection(DbUtil.ConnString)) { SqlCommand cmd = conn.CreateCommand(); //查询Scores表中是否已有用户信息 cmd.CommandText = @"SELECT * FROM Scores WHERE UserName =@UserName"; cmd.CommandType = System.Data.CommandType.Text; cmd.Parameters.Add(new SqlParameter("@UserName", userName)); cmd.Parameters.Add(new SqlParameter("@Score", value)); conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); //如果Scores表中用户积分已存在就在原来的基础上加10份;否则就插入新的用户积分数据 if (reader.Read()) { //在用户原有积分基础上加10分 cmd.CommandText = @"UPDATE Scores SET Score+=10 WHERE UserName = @UserName"; //关闭reader reader.Close(); //执行SQL语句 cmd.ExecuteNonQuery(); } else { reader.Close(); //插入新的用户积分数据 cmd.CommandText = @"INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)"; cmd.ExecuteNonQuery(); } } }}

转载地址:https://blog.csdn.net/zwj_jyzl/article/details/81534062 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:委托与事件(浅度分析)—委托
下一篇:组合模式

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月29日 05时52分43秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

「权威发布」2019年大学生电子设计竞赛,仪器设备和主要元器件清单 2019-04-29
「重磅猜题之第二篇」2019年大学生电子设计竞赛 2019-04-29
知乎:硬件和软件哪个吃香? 2019-04-29
中国深圳,600架无人机的盛典! 2019-04-29
干货分享 JVM 之第 3 篇 —— Java 内存结构相关 2019-04-29
干货分享 JVM 之第 4 篇 —— 掌握 Jmeter 压力测试工具,熟悉 Jconsole.exe 工具 2019-04-29
干货分享 JVM 之第 5 篇 —— 类加载器 2019-04-29
干货分享 JVM 之第 6 篇 —— SpringBoot2.0 框架性能调优 2019-04-29
基于 Hystrix 高并发服务限流第 1 篇 —— 必须了解的相关概念 2019-04-29
基于 Hystrix 高并发服务限流第 2 篇 —— 服务隔离(线程池隔离、信号量隔离) 2019-04-29
基于 Hystrix 高并发服务限流第 3 篇 —— 服务熔断、服务降级 2019-04-29
基于 Hystrix 高并发服务限流第 4 篇 —— 基于 Feign 实现服务熔断降级处理 2019-04-29
基于 Hystrix 高并发服务限流第 5 篇 —— Hystrix 监控 2019-04-29
Eureka 如何快速的、优雅的停止某个微服务 2019-04-29
Eureka 实现安全认证 2019-04-29
基于 Hystrix 高并发服务限流第 6 篇 —— 服务限流,基于 RateLimiter 实现 2019-04-29
Nginx 反向代理、负载均衡配置、Location正则表达式 2019-04-29
SpringBoot + WebSocket 实现前后端的收发消息 2019-04-29
SpringBoot 整合 JWT 实现统一认证 2019-04-29
SpringBoot 使用 CompletableFuture 实现非阻塞异步编程 2019-04-29