开始
😓汗,先说重构开始的感受把,三层学完后就开始准备敲机房重构了,这次的机房重构是在三层登录的基础上加了设计模式。然后就有了第二版的七层重构。对于这个项目登录敲了一两天,为什么只用一两天呢?因为习惯性的喜欢站在巨人的肩膀上学习。所以快纳!网上七层代码一大堆,只需要喵准一篇感觉差不多的抄就完事了,当然抄代码不是长久之事,网上的登录相当于给自己指了一个方向,后边的路还需要自己走。重构开始时都会觉得各种难,不会,不想敲,先放放,这放下就是一个月或着更长的时间。总结下,重构需要做的就是调整好自己心态,有项目拖延症的童鞋可以想办法如何让自己在最短的时间内把项目走完,做好时间管理。
七层之间的联系:
简单理解七层
- UI:是用户所能看的到的界面,用来接收和显示用户的请求,将参数整体传递给外观层。
- Facade:外观层是为了降低U层和B层之间的耦合
- BLL:业务逻辑层,进行逻辑判断。
- Factory:通过配置文件和抽象工厂我们可以实现不更改代码,更换配置文件中的Key value就可更换数据库。
- IDAL:接口层是用于定义一个统一的接口,解除B层和D层之间的耦合。
- DAL:实现IDAL层定义的全部接口。——SqlHelper:将D层中需要重复使用的连接数据库代码写到一个层里面,为了减少代码冗余。
- Entity:实现各个层中的数据传递
从设计模式学习到三层架构在到七层架构,应用设计模式更多的是减少各层之间的耦合度。
代码部分:
UI层
private void BtnOK_Click(object sender, EventArgs e)
{
if (txtUserName.Text.Trim() == "")
{
MessageBox.Show("请输入账号", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (txtPassword.Text == "")
{
MessageBox.Show("请输入密码", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
// //实例化实体层
Entity.User_Info user = new Entity.User_Info();
CardNo = Convert.ToInt32(txtUserName.Text.Trim()); //获取用户id
PassWord = txtPassword.Text.Trim();
user.UserID = Convert.ToInt32(txtUserName.Text.Trim());
user.PWD = txtPassword.Text;
//实例化登录外观将参数传递给外观层
//Facade.LoginFacade Facade = new Facade.LoginFacade();
//实例化外观
Facade.LoginFacade loginfacade = new Facade.LoginFacade();
Boolean flag;
//调用外观的方法,返回给user
flag = loginfacade.SelectUser(user);
if (flag != false)
{
//隐藏当前窗体
this.Hide();
this.DialogResult = System.Windows.Forms.DialogResult.OK; //DialogResult 是Form类的一个属性,ShowDialog()是Form类的一个方法也就是函数
DataTable level = loginfacade.SeletLevel(user);
if (level.Rows[0][2].ToString().Trim() == "一般用户")
{
//实例化窗体
StudentMain frmstudent = new StudentMain();
//显示实例化的学生界面
frmstudent.Show();
}
else if (level.Rows[0][2].ToString().Trim() == "操作员")
{
FrmOperatorMain frmoperatormain = new FrmOperatorMain();
frmoperatormain.Show();
}
else
{
FrmOperatorMain frmoperatormain = new FrmOperatorMain();
frmoperatormain.Show();
}
}
else
{
MessageBox.Show("密码或者用户名错误");
}
}
Facade层:
public class LoginFacade
{
public Boolean SelectUser(Entity.User_Info user)
{
bool flag; //定义一个bool类型变量flag
//实例化B层
BLL.LoginManager man = new BLL.LoginManager();
//实例名.BLL层得方法,返回到外观层。
flag = man.UserBLL(user);
return flag; //返回布尔flag
}
public DataTable SeletLevel(Entity.User_Info level1)
{
LoginManager levelBll = new LoginManager();
DataTable level = levelBll.LevelBLL(level1);
//返回DataTable level
return level;
}
}
BLL层:
public class LoginManager
{
public bool UserBLL(Entity.User_Info user)
{
//实例化工厂层
Factory.LoginFactory loginFactory = new Factory.LoginFactory();
//调用工厂方法创建接口
IDAL.ILoginIDAL loginIdal = loginFactory.CreateUser(); //调取工厂中方法,利用反射机制实例化DAL层
//接收D层的返回值
DataTable table = loginIdal.SelectUser(user); //缺少引用data //调取DAL层的方法
bool flag;
//返回的DataTable类型,如果他的行数等于0,说明没有符合该账户密码的账户
if(table.Rows.Count==0) //表中的行等于0
{
flag = false;
}
else
{
flag = true;
}
return flag;
}
public DataTable LevelBLL(Entity.User_Info UserInfo)
{
//实例化工厂
Factory.LoginFactory fact = new Factory.LoginFactory();
//调用工厂方法创建接口
IDAL.ILoginIDAL idal = fact.CreateUser();
//接收D层的返回值
DataTable level = idal.SelectUser(UserInfo);
return level;
}
}
Factory层:
public class LoginFactory
{
//引用配置文件建DB对应的值DAL
//ConfigurationManager类需要在引用中添加System.Configuration
string StrDB = ConfigurationManager.AppSettings["DB"];
public IDAL.ILoginIDAL CreateUser()
{
string ClassName = StrDB + "." + "LoginDAL";
//Assemble.Load()在给定程序集的情况下,加载改程序集:CreateInstance()方法:使用默认构造函数创建指定类型的实例;
return (IDAL.ILoginIDAL)Assembly.Load(StrDB).CreateInstance(ClassName);
}
//将DAL属性的路径改为UI/bin/Debug
}
IDAL层:
public interface ILoginIDAL
{
DataTable SelectUser(Entity.User_Info UserInfo);
}
DAL层:
public class LoginDAL:IDAL.ILoginIDAL
{
public DataTable SelectUser(Entity.User_Info user) //缺少引用
{
//实例化SqlHelper一个数据查询的对象
SQLHelper.SqlHelper sqlHelper = new SQLHelper.SqlHelper();
//定义需要传递的参数
SqlParameter[] sqlParams = { new SqlParameter("@UserName", user.UserID), new SqlParameter("@Password", user.PWD)};
string sql = @"SELECT * FROM User_Info WHERE UserID=@UserName and PWD =@Password"; //查询sql数据
DataTable table = sqlHelper.ExecuteQuery(sql, sqlParams, CommandType.Text); //将参数传入SqlHelp类
return table; //返回表到BLL层
}
Entity层:
namespace Entity //实体层
{
//属性,一般是为外部提供数据,主要用来描述对象的静态特征,所以,属性一般是public。
//属性具备get和set方法,可以在方法里加入逻辑处理数据,灵活拓展使用。
//字段一般是private,字段是可读可写的
public class User_Info //登录表
{
//定义用户ID字段
public int UserID { get; set; }
//定义用户密码字段
public string PWD { get; set; }
//定义用户等级字段
public string Level { get; set; }
}
}
SqlHelper:
namespace SQLHelper
{
public class SqlHelper
{
private SqlConnection conn = null; //用前先引用SqlClient
private SqlCommand cmd = null;
private SqlDataReader sdr = null; //从数据库只读
public SqlHelper()
{
string connStr = ConfigurationManager.AppSettings["ConnStr"]; //从客户端访问配置文件,读取连接数据库信息,引用程序集的命名空间
conn = new SqlConnection(connStr); //打开数据库的连接,此时并未连接成功?
}
private SqlConnection GetConn()
{
if(conn.State==System.Data.ConnectionState.Closed) //枚举ConnectionState,用于描述数据源当前的连接状态
{
conn.Open();//连接数据库
}
return conn;
}
public DataTable ExecuteQuery(string cmdText,SqlParameter[] paras, CommandType ct)
{
DataTable dt = new DataTable();//实例化数据库内存中的一个表
SqlCommand cmd = new SqlCommand(cmdText,GetConn()); //cmdText:查询的文本;getConn():连接数据库的方法
cmd.CommandType = ct; //指定命令对象的执行形式,默认为text
cmd.Parameters.AddRange(paras);//将参数加入到参数集中
using (sdr =cmd.ExecuteReader(CommandBehavior.CloseConnection)) //在执行命令时,将关联Connection 对象关闭时关联DataReader 对象已关闭
{
dt.Load(sdr); //将提供的数据源中的值填充到DataTable,如果已存在,则合并
}
cmd.Parameters.Clear();
return dt; //返回表到DAL层
}
public DataTable ExecuteQuery(string cmdText, CommandType ct)
{
DataTable dt = new DataTable();
cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
dt.Load(sdr);
}
return dt;
}
public int ExecteNonQuery(string cmdText, CommandType ct)
{
int res;
try
{
cmd = new SqlCommand(cmdText, GetConn());
cmd.CommandType = ct;
res = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
cmd.Parameters.Clear();
return res;
}
public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct)
{
int res;
using (cmd = new SqlCommand(cmdText, GetConn())) //将SQL语句作为参数能够防止SQL注入
{
cmd.CommandType = ct;
cmd.Parameters.AddRange(paras);
res = cmd.ExecuteNonQuery();
}
cmd.Parameters.Clear();
return res;
}
}
}
UI层下的配置文件:
<appSettings>
<add key="ConnStr" value="server=DESKTOP-4F7J223;user=sa;password=123456789.+; database=charge_sys" />
<add key="DB" value="DAL" />
</appSettings>