机房收费-七层架构

    至于为什么不采用简单的三层架构,偏偏采用七层,甚是不理解,不过不理解归不理解,东西还是得照做啊;

  《 所谓三层、七层其实核心理念还是没有变的,无非就是划分层次多了,层与层之间的耦合性降低了,也就是多传几次值;不过F(外观)层到现在也是不理解,虽然说是解耦,但是没有体会到它的真正作用,我想应该是我哪里写的有问题,不然怎么会感觉F层和B层写的代码神相似呢,跪求各位大神在评论解释说明下!

    当然通过借鉴他人的话语理解就是将外观层写成一个整体,然后B层中的各种类都调用这个外观,剪断U层和B层错综复杂的交互,然而这个整体,迄今为止还不知道该怎么写比较合适? 》

    当然本篇博客是优化过的,七层之间传递关系图这里就不细写了,哪里有问题,欢迎指出,万分感谢;

(一)、当然我们得从最底层看起,所以我选择了“U层”,别问我为什么?你都不知道高层要干啥,怎么去底层写代码!

        public static string loginName="";
        private void btnLogin_Click(object sender, EventArgs e)
        {
            string name = txtName.Text.Trim();
            string pwd = txtPwd.Text.Trim();
            string type;
            UserFacade uFacade = new UserFacade();
            LoginState lState = uFacade.Login(name,pwd,out type);//通过out传递从数据库返回的数据,然后在判断
            switch (lState)
            {
                case LoginState.Ok:
                    FormMain main = new FormMain();
                    main.Tag = type;//判断是操作员窗体还是管理员
                    loginName = name;
                    main.Show();
                    this.Hide();
                    break;
                case LoginState.NameError:
                    MessageBox.Show("用户名错误");
                    break;
                case LoginState.PwdError:
                    MessageBox.Show("密码错误");
                    break;
                default:
                    break;
            }

        }

    当然了U层一开始也写不出这么NX的代码的,慢慢摸索出来的,那现在聊聊U层起初写点什么吧;

    目的:通过数据库中返回的数据,判断登录是否成功(成功、账号错误、密码错误),如果成功后则,判断登录名的类型,从而展示主窗体;否则返回提示信息(账号或者密码错误)。

    这么一说,那到底该怎么写,判断三者是否用select ..case或者if..else if..else语句,那么应该返回什么进行判断呢?其实在参数中通过bool类型转换即可,但是好像需要有三种,不仅仅返回登录成功或者失败,所以这里“增加”了-实体类(Entity):辅助返回值,三种类型

namespace Entity
{
    public enum LoginState
    {
        Ok,
        NameError,
        PwdError

    }
}

(二)、当然真正的关于这一层的实体得写成这个样子-“Entity层”,实体层中一定要写完数据库表中所有的字段,如果有主外键等等在实现功能的时候需要扩充实体层的话,不妨另写一个OtherClass类,“Partial”修饰符能够很好的把本类和OtherClass类无缝结合。

namespace Entity
{
    public partial class UserInfo
    {
        public int UId { get; set; }
        public string UName { get; set; }
        public string UPwd { get; set; }
        public string UType { get; set; }
    }
}

(三)、此时也当然也不可能在U层写出上面那些代码,但是知道了高层想要做什么,此时底层还不会写代码吗?-转D层"Dal";

            或许有伙伴有疑问了,为什么仅仅返回传递一个name参数,而没有pwd,这里我们想通过账号查找其它信息,所以仅仅有一个参数即可;

        public UserInfo GetByName(string name)
        {
            UserInfo ui = null;
            string sql = "select * from userinfo where uname=@name";
            SqlParameter p = new SqlParameter("@name", name);
            DataTable dt = SqliteHelper.GetDateTable(sql, p);
            if (dt.Rows.Count>0)
            {
                ui = new UserInfo()
                {
                    UId = Convert.ToInt32(dt.Rows[0][0]),
                    UName = name,
                    UPwd=dt.Rows[0][2].ToString(),
                    UType=dt.Rows[0][3].ToString()
                };
            }
            return ui;

        }

(四)、那么接下来看看D层需要实现的接口层"IDal"层,声明接口实现方法,让子类去重写,利用反射技术;

namespace IDAL
{
    public partial interface UserIDal
    {
        //List<UserInfo> GetList();
        //int Insert(UserInfo ui);
        //int Update(UserInfo ui);
        //int Delete(int id );
        UserInfo GetByName(string name);
    }
}

(五)、然后是工厂层“Factory”(采用抽象工厂+反射),外加“配置文件”便于后期更换不同类型的数据库

namespace Factory
{
    public partial class DataAccess
    {
        private static readonly string AssemblyName = ConfigurationManager.AppSettings["Dal"];
        //前提D层中“DAL.sqlserver”表名命名的,才方便更换数据库
        //private static readonly string middleName = ConfigurationManager.AppSettings["DB"];
        public static UserIDal CreateUser()
        {
            string className = AssemblyName + "." + "UserDal";
            return (IDAL.UserIDal)Assembly.Load(AssemblyName).CreateInstance(className);
        }
    }
}

配置文件<App.config>中信息需要这样写;这里的话,我才用appSettings和ConnectionStrings两种发挥不同的作用,当然有些文章中采用的一种,感觉稍微有些误用了,虽然最终的目的都可以实现。

<configuration>
  <appSettings>
    <add key="Dal" value="DAL"/>//反射部分需要
    <add key="DB" value="Sqlserver"/>//更换不同数据库,只需要改变这里
  </appSettings>
  <connectionStrings>
    <add name="sql" connectionString="server=DESKTOP-GCS3QKO\SQLEXPRESS;uid=sa;pwd=1;database=Charge_sys"/>
  </connectionStrings>

(六)、接下来便是B层“BLL”,充分体现了依赖倒转原则:实现依赖于抽象;

namespace BLL
{
    public partial class UserBll
    {
        private UserIDal uIDal;
        public UserBll()
        {
            uIDal = DataAccess.CreateUser();
        }
        public LoginState Login(string name,string pwd,out string type)
        {
            type = null;
            //根据用户名进行对象查询
            UserInfo ui = uIDal.GetByName(name);
            if (ui==null)
            {
                return LoginState.NameError;
            }
            else
            {
                if (ui.UPwd.Equals(pwd))
                {
                    type = ui.UType;
                    return LoginState.Ok;
                }
                else
                {
                    return LoginState.PwdError;
                }
            }
        }
    }
}

(七)、然后是外观层“Facade”-也就是博文开头说的,自己发现没有什么意思+不理解的这一层;

namespace Facade
{
    public partial class UserFacade
    {
        private UserBll uBll;
        public UserFacade()
        {
            uBll = new UserBll();
        }
        public LoginState Login(string name, string pwd, out string type)
        {
            type = null;
            return uBll.Login(name,pwd,out type);
        }
     }
}

      各位伙伴有没发现,F层、B层实例化其他层的时候,都是通过构造方法实现的,作用要好比于直接私有实例化;

    到这里的话,整个七层架构中登录功能也算完成了,不知道各位有没理解和消化,当然立马消化的话,还是有些困难的,当初我也是敲了几个窗体后才消化的,之前仅仅称为理解;希望读者可以在下方留下宝贵的见解,如果感觉好的话,请在博文“右上方点赞”支持小编;


评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值