三层架构
三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer) 、业务逻辑层(Business Logic Layer) 、数据访问层(Data access layer) 。区分层次的目的即为了“高内聚低耦合”的思想。
在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。
微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。
三层原理
3个层次中,系统主要功能和业务逻辑都在业务逻辑层进行处理。
所谓三层体系结构,是在客户端与数据库之间加入了一个“中间层”,也叫组件层。
这里所说的三层体系,不是指物理上的三层,不是简单地放置三台机器就是三层体系结构,也不仅仅有B/S应用才是三层体系结构,三层是指逻辑上的三层,即把这三个层放置到一台机器上。
通常情况下,客户端不直接与数据库进行交互,而是通过COM/DCOM通讯与中间层建立连接,再经由中间层与数据库进行交互。
各层对比
各层 | 作用 | 重要性 |
---|---|---|
UI层 | 提供界面,输入输出指令或数据 | ※※※※ |
业务层 | 传达数据,分析结果 | ※※※※※ |
数据层 | 操纵数据库,增删改查 | ※※※※ |
优缺点
优点
1.明确了“高内聚低耦合”的思想;
2.操作员只需要关注整个项目中的一层;
3.降低层与层之间的依赖;
4.有利于标准化;
5.利于各层逻辑的复用;
6.结构更加的明确;
7.在后期维护的时候,极大地降低了维护成本和维护时间;
缺点
1、降低了系统的性能。
这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
2、有时会导致级联的修改。
这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。
3、增加了开发成本。
通过分层设计,就会增加各个部门的精英人数,更加细致的划分人员,使得开发费用增加。
例子展示
例子说明
利用三层实现以下功能:1.登陆窗体,判断登陆是否成功;2.登陆成功增加10点积分;
程序设计思考
- 思考
要利用三层架构实现登陆窗体,首先要熟悉登陆的流程,要建立各个层,然后要确定每层的主要功能是什么,最后代码实现。
- 登陆流程图
关键代码展示
- 首先要从UI层开始;
private void button1_Click(object sender, EventArgs e)
{
//传值,将两个text传给userName 和password。
string userName = txtUserName.Text.Trim();
string password = txtPassWord.Text;
//实例化业务层
Login.BLL.LoginManager mgr = new Login.BLL.LoginManager(); //实例化一个业务层的LoginManager,用于判断逻辑
Login.Model.UserInfo user = mgr.UserLogin(userName, password); //实例化一个业务层的Model,用于给userLogion赋值name,password。
MessageBox.Show("登陆用户:"+userName ); //显示登录信息。
}
- 然后要到业务层,判断用户是否登陆成功;
//管理登录类,用于判断用户是否登陆成功。
public class LoginManager
{
public Login.Model.UserInfo UserLogin(string userName, string password) //UserLogin方法,判断登录信息是否正确
{
Login.DAL.UserDAO uDao = new Login.DAL.UserDAO(); //实例化一个数据层登录
Login.Model.UserInfo user= uDao.SelectUser(userName,password); //实例化一个model,用于给数据层的Selectuser赋值。
if (user != null) //login successful
{
Login.DAL.ScoreDAO sDao = new Login.DAL.ScoreDAO();
sDao.UpdateScore(userName, 10); //增加积分
return user;
}
else
{
throw new Exception("登陆失败");
}
}
}
- 接下来是到数据层,判断用户名和密码是否正确;
public class UserDAO
{
public Login.Model .UserInfo SelectUser (string userName, string passWord)
{
//throw new NotImplementedException(); //返回bool值,判断是否登陆成功。
using (SqlConnection conn=new SqlConnection (DBUtil .ConnString )) //建立数据库连接。
{
#region 连接数据库,创建连接对象cmd,需要引用using System.Data.SqlClient;引用数据库命名空间。
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));
#endregion
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); //获取指定列的 32 位有符号整数形式的值
user.UserName = reader.GetString(1);
user.Password = reader.GetString(2);
if (!reader.IsDBNull(3))
{
user.Email = reader.GetString(3);
}
}
return user; //很重要
}
}
}
- 在数据层对比后,将结果返还给业务层,再传给UI层,UI层将结果输出给用户。如果成功,在业务层判断后,需要为此用户添加积分,就要再次到数据层,为用户增加积分;
public class ScoreDAO
{
public void UpdateScore(string userName, int value) //更新积分的方法UpdateScore
{
using(SqlConnection conn=new SqlConnection (DBUtil .ConnString))
{
#region 连接数据库,创建连接对象cmd
SqlCommand cmd = conn.CreateCommand();
cmd .CommandText =@"INSERT INTO SCORE (UserName ,Score) Values(@UserName,@Score)";
cmd.Parameters .Add (new SqlParameter ("@UserName",userName));
cmd.Parameters .Add (new SqlParameter("@Score",value ));
#endregion
//打开数据库连接。
conn.Open();
//执行SQL句,返回受影响行数(判断执行SQL句是否成功)
cmd.ExecuteNonQuery ();
}
}
}
- 温馨提示:在三层数据传递的过程中,会涉及到一个上传下蹦作用的实体,帮助我们传输数据;(具体作用看链接 [ 实体 ])
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; }
}
}
学习心得
刚刚接触了三层架构,初步感觉运用三层架构是比较麻烦的,但是从后期维护、长久的使用来想,三层确实是要发展的趋势。通过这个例子的学习,我也初步了解了实体的概念,很多情况下我们都需要开放自己,让自己接受新知识。加油吧!骚年!
更多了解:
【作者:王雷 http://blog.csdn.net/kisscatforever】