三层结构是基于模块化程序设计的思想,为实现分解应用程序的需求,而逐渐形成的一种标准模式的模块划分方法。三层架构的优点在于不必为了业务逻辑上的微小变化而迁至整个程序的修改,只需要修改商业逻辑层中的一个函数或一个过程;增强了代码的可重用性;便于不同层次的开发人员之间的合作,只要遵循一定的接口标准就可以进行并行开发了,最终只要将各个部分拼接到一起构成最终的应用程序。


总结的知识要点:

点此看大图

三层架构开发模式 三层架构模式图_数据访问层

三层结构通常是指数据访问层、业务逻辑层和表示层。三层结构之间的关系如下图所示。


三层架构开发模式 三层架构模式图_三层架构开发模式_02




表示层位于最上层,用于显示和接收用户提交的数据,为用户提供交互式的界面。表示层一般为Windows窗体应用程序或Web应用程序。


业务逻辑层是表示层和数据访问层之间沟通的桥梁,主要负责数据的传递和处理。


数据访问层主要实现对数据的读取、保存和更新等操作。



在三层结构中,各层之间相互依赖,表示层依赖于业务逻辑层,业务逻辑层依赖于数据访问层



很重要的实体类,关系图示:


三层架构开发模式 三层架构模式图_业务逻辑_03


实例1:小的demo来学习三层(分层)


通过U层来获取登录的数据

namespace LoginUI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            //IDbConnection conn = new SqlConnection("c......");
            //IDbCommand cmd = conn.CreateCommand();
            //cmd.CommandText = "Select UserName From USERS WHERE ....";
            //cmd.ExecuteReader();
            //读取用户名和密码
            string userName = txtUserName.Text.Trim();
            string password = txtPassword.Text;
            Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();//实例化对象
            Login.Model.UserInfo user = mgr.UserLogin(userName, password);

            MessageBox.Show("登录用户:" + user.UserName);

        }
    }
}


业务逻辑主要是对于数据的有效性进行校验,逻辑的判断,记录是否存在都放在BLL层


namespace Login.BLL
{
    //定义了一个新类,业务逻辑层,判断数据是否有效

    public class LoginManager
    {
        public Login.Model.UserInfo UserLogin(string userName, string password)
        {
            //通过字段去数据库调用该用户名与密码的信息
            Login.DAL.UserDAO uDao = new Login.DAL.UserDAO();
            Login.Model.UserInfo user = uDao.SelectUser(userName, password);
            //去判断是否存在,返回结果提示给用户
            if (user != null)// login successfully.
            {
                Login.DAL.ScoreDAO sDao = new Login.DAL.ScoreDAO();
                sDao.UpdateScore(userName, 10);
                return user;
            }
            else
            {
                //抛出
                throw new Exception("登录失败。");
            }
           
        }
    }
}

通过在数据访问层来对数据库的操作

namespace Login.DAL
{
    public class UserDAO
    {
        //通过此去数据库查询是否有此记录
        public Login.Model.UserInfo SelectUser(string userName, string password)
        {
            //实例化一个数据库链接
            using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = @"SELECT ID, UserName, Password,Email 
                                    FROM USERS WHERE UserName=@UserName AND Password=@Password";
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add(new SqlParameter("@UserName",userName));
                cmd.Parameters.Add(new SqlParameter("@Password",password));

                conn.Open();
                //读取数据
                SqlDataReader reader = cmd.ExecuteReader();
                //判断是该条记录否存在
                Login.Model.UserInfo user = null;
                while (reader.Read())
                {
                    if (user == null)
                    {
                        user = new Login.Model.UserInfo();
                    }
                    //字符转译
                    user.ID = reader.GetInt32(0);
                    user.UserName = reader.GetString(1);
                    user.Password = reader.GetString(2);// not suggestion
                    if (!reader.IsDBNull(3))
                    {
                        user.Email = reader.GetString(3);
                    }
                }

                return user;
            }
        }
    }
}

判断是否存在该卡号,之后再增加相应的积分

//数据访问层
namespace Login.DAL
    
{
    public class ScoreDAO
    {//登录成功的话就更新对于用户的积分
        public void UpdateScore(string userName, int value)
        {
            using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = @"INSERT INTO SCORES(UserName, Score) Values(@UserName,@Score)";
                cmd.Parameters.Add(new SqlParameter("@UserName",userName));
                cmd.Parameters.Add(new SqlParameter("@Score",value));
                //打开
                conn.Open();
                //执行查询操作
                cmd.ExecuteNonQuery();
            }
        }
    }
}


负责与对应数据库的连接

namespace Login.DAL
{
    class DbUtil
    {
        //打开数据库,访问对应的数据库
        public static string ConnString = @"Server=服务器地址; Database=数据库名称; User ID=sa; Password=123456";
    }
}

业务实体类,是所有用户的共享数据的中转站

namespace Login.Model
{
    //业务实体,与数据库中的表对应()
    public class UserInfo
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }

    }
}


总结

并非所有的软件开发都需要三层架构,小型简单的软件没有必要使用,合理的使用三层架构,可以使每层各负其职,任意一层不管其他层是否存在,只需要有对应的接口就可以调用,好处是功能单一,降低了和其他模块的耦合,在设计中我们尽量要把不变的操作都封装,这样简少代码量,增加了代码复用的效果在维护和扩展上,我们提高了效率。


接下来深入剖析“三层架构中的实体类”