首页 > 代码库 > 三层架构—简析

三层架构—简析

    三层学习完了,第一次验收的时候,自己理解的也不是很到位,后来又重新敲了一遍登陆例子,查阅了一些资料

进行第二次验收才感觉清晰了许多。之前画时序图时我就想过时序图基本上也是很好的体现了三层,当时也和别人讨

论过这个问题。直到学完三层后,更加证明了这一点。

    下面我将从理论和实践两个角度总结一下三层。


理论篇


    为什么使用三层架构?


    说白了,分层的目的是想将复杂问题简单化,也就是面向对象技术所崇尚的“高内聚,低耦合”。当业务复杂到

一定程度,数据存储在独立的存储介质时适合用三层架构。


    什么是三层架构?


    通常意义上的三层架构(3-tier architecture)就是将整个业务应用划分为:表现层(UI)、业务逻辑层

(BLL)、数据访问层(DAL)。

    图解



    表现层(UI):主要是指人机交互界面。用于接收用户输入的数据和显示处理后用户需要的数据。

    业务逻辑层(BLL):连接UI和DAL的桥梁。

    数据访问层(DAL):实现数据库的增、删、改、查。

    实体类(Model):不属于三层的范畴,个人理解的建立实体类的目的是将载入的数据库中的数据放入其中,

UI、BLL、DAL,哪个需要就从实体类中获取。封装数据,避免了传参数造成的复杂,从而避免了各个层与数据库的直

接接触,造成数据交叉。各个层只需要和实体层Model打交道即可。

    点睛

    各个层各司其职,只负责自己专属的功能,提高了内聚性,减少了彼此之间的耦合。Model是传输数据的业务数

据模型,不是数据库中的数据,Model是避免出现数据交而建立的。


    如何搭建?


    优缺点?


    优点

        1、开发人员可以只关注整个结构中的其中某一层;

        2、可以降低层与层之间的依赖;

        3、有利于标准化,可以很容易的用新的实现来替换原有层次的实现;

        4、在后期维护的时候,极大地降低了维护成本和维护时间

    缺点

        1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获

取相应的数据,如今却必须通过中间层来完成。

        2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为

保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

        3、增加了开发成本。


实战篇


    下面是一个登录窗体的DEMO


    UI层的代码


<span style="font-family:KaiTi_GB2312;font-size:18px;">namespace LoginUI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {

            string userName = txtUserName.Text.Trim();   
            string password = txtPassword.Text;
            Login.BLL.LoginManager mgr = new Login.BLL.LoginManager();   //重载BLL层
            Login.Model.UserInfo user = mgr.UserLogin(userName, password);

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

        }
    }
}
</span>

    UI层,人机交互。需要引用BLL和Model层,从代码中可以看出UI层不包含任何逻辑判断的代码和跟数据库有关的

代码。


    BLL层的代码


<span style="font-family:KaiTi_GB2312;font-size:18px;">namespace Login.BLL
{
    public class LoginManager
    {
        public Login.Model.UserInfo UserLogin(string userName, string password)      //获得Model中封装的数据库中的数据(UI层中的)
        {

            Login.DAL.UserDAO uDao = new Login.DAL.UserDAO();        //实例化UserDAO类
            Login.Model.UserInfo user = uDao.SelectUser(userName, password);           
            if (user != null)                                          // 载入成功
            {
                Login.DAL.ScoreDAO sDao = new Login.DAL.ScoreDAO();             //知道数据库连接成操作命令
                sDao.UpdateScore(userName, 10);
                return user;
            }
            else
            {
                throw new Exception("登录失败。");
            }
</span>

    从代码中可以看出BLL层也不和数据库打交道,没有SQL语句。需要引用DAL和Model层。


    DAL层代码


<span style="font-family:KaiTi_GB231<span style="font-family: Arial, Helvetica, sans-serif;">2;font-size:18px;">namespace Login.DAL</span>
{
    public class UserDAO
    {
        public Login.Model.UserInfo SelectUser(string userName, string password)    //获取Model中的表中的数据,返回的是数据模型
        {
            using (SqlConnection conn = new SqlConnection(DbUtil.ConnString))      //建立数据库连接
            {
                SqlCommand cmd = conn.CreateCommand();  //表示要对 SQL Server 数据库执行的一个 Transact-SQL 语句或存储过程。 实例化一个接口,用以执行SQL指令
                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;               //默认值是Null
                while (reader.Read())                          //读取数据库中的数据
                {
                    if (user == null)
                    {
                        user = new Login.Model.UserInfo();        //当Model是Null的话才加载数据
                    }
                    user.ID = reader.GetInt32(0);
                    user.UserName = reader.GetString(1);
                    user.Password = reader.GetString(2);
                    if (!reader.IsDBNull(3))                  //如果Email不是Null的话,才能读取
                    {
                        user.Email = reader.GetString(3);
                    }
                }

                return user;
            }
        }
    }
}
</span>

    从代码中可以看出是直接和数据库打交道的,没有跟窗体控件有关的内容。需要引入Model层。


个人小结


    分层的目标是为了“高内聚,低耦合”,分层可将复杂的简单化,当需求需要改变时,你只需要该相应部分而不

用大范围的修改。分层还提高了可维护性和可扩展性,但并不是所有的都要分层,业务逻辑简单,没有真正的数据存

储层这时就不需要分层,如果分层反而会增加复杂度。所以我们平常在使用时要注意灵活应用。