欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

三层架构

程序员文章站 2022-03-14 10:12:41
...

为什么要用三层

  说到三层,先来说一说两层结构。两层结构将界面展示、业务逻辑、数据访问等都写到一起,如果用户需求变化,就需要对整个项目进行大量修改,系统的维护和升级极其不利;而且界面层直接访问数据库,还会有安全隐患。结构如下图所示:
三层架构
  所以基于两层结构的局限性,三层结构就出现了。三层结构符合“高内聚、低耦合”的特点,每个层职责明确。利用分层,降低了层间依赖,使系统的耦合更加松散,从而使系统更加容易维护和复用。
  比如:如果需求有变化,只需要更改相应的业务逻辑层;或者要改变数据库的时候,只需要将原来的数据访问层替换掉或者增加新的就可以了,而不需要牵扯到整个项目。
  三层架构虽好,但是也不是每个项目都必须采用这种结构,三层结构用于比较复杂的大型系统,如果系统比较小,则没必要将问题复杂化。

何为三层

三层架构
三层由显示层(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
{
    /// <summary>
    /// 查询用户是否存在并返回用户信息
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="password">密码</param>
    /// <returns></returns>
    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 aaa@qq.com AND aaa@qq.com";
            //指示执行的是存储过程还是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
{
    /// <summary>
    /// 更新用户积分
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="value">要增长的积分</param>
    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 aaa@qq.com";                
            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();
            }
        }                        
    }
}
相关标签: 三层实现