zoukankan      html  css  js  c++  java
  • 贫血模型和充血模型

    一、贫血模型

    所谓贫血模型,是指Model 中,仅包含状态(属性),不包含行为(方法),采用这种设计时,需要分离出DB层,专门用于数据库操作。

    二、充血模型

    Model 中既包括状态,又包括行为,是最符合面向对象的设计方式。

    以下为举例说明:

    对于员工Employee来说,每个员工的属性有Id,Name,Sex,BirthDay,Parent(上级),行为有查找,保存,删除,职位调整(更换上级) 等

    采用贫血模型实现

    Model:

    public class Employee
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Sex { get; set; }
            public DateTime? BirthDay { get; set; }
            /// <summary>
            /// 直属上级的Id
            /// </summary>
            public string ParentId { get; set; }
        }
    View Code

    DB 层

    //实现方法略    
    public class EmpDAO
        {
            public static bool AddEmployee(Employee emp);
            public static bool UpdateEmployee(Employee emp);
            public static bool DeleteEmployee(Employee emp);
            public static Employee GetEmployeeById(string Id);
        }
    View Code

    BLL 层

    public class EmpBLL
        {
            public void Test()
            {
                Employee emp1 = new Employee() { Id = System.Guid.NewGuid().ToString(), Name = "张三", Sex = "" };
                Employee emp2 = new Employee() { Id = System.Guid.NewGuid().ToString(), Name = "李四", Sex = "", ParentId = emp1.Id };
               //插入员工
                EmpDAO.AddEmployee(emp1);
                EmpDAO.AddEmployee(emp2);
    
                //取员工的上级
                var emp2Parent = EmpDAO.GetEmployeeById(emp2.ParentId);
                var emp2Parent_Parent = EmpDAO.GetEmployeeById(emp2Parent.ParentId);
    
                //删除员工
                EmpDAO.DeleteEmployee(emp1);
                EmpDAO.DeleteEmployee(emp2);
            }
        }
    View Code

    若采用充血模型设计,则应只分两层 ,Model 层(包含状态和行为)和Service(BLL) 层

    Model 层

     public class Employee
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public string Sex { get; set; }
            public DateTime? BirthDay { get; set; }
            /// <summary>
            /// 直属上级的Id
            /// </summary>
            public string ParentId { get; set; }
            private Employee _parent;
    
            public static Employee query(string id)
            {
                Employee emp = new Employee();
                //实现略,仅需填充emp的熟悉即可
                return emp;
            }
            /// <summary>
            /// 保存对象,实现略
            /// </summary>
            /// <returns></returns>
            public bool Save()
            {
                return true;
            }
            /// <summary>
            /// 删除对象,实现略
            /// </summary>
            /// <returns></returns>
            public bool Drop()
            {
                return true;
            }
            /// <summary>
            /// 上级领导,此处直接获得了Employee对象
            /// </summary>
            public Employee Parent
            {
                get
                {
                    if (_parent != null)
                    {
                        return _parent;
                    }
                    else
                    {
                        _parent = query(this.ParentId);
                        return _parent;
                    }
                }
                set
                {
                    _parent = value;
                    this.ParentId = _parent.Id;
                    Save();
                }
            }
        }
    View Code

    Service 层

    public class EmpService
        {
            public void Test()
            {
                Employee emp1 = new Employee() { Id = System.Guid.NewGuid().ToString(), Name = "张三", Sex = "" };
                Employee emp2 = new Employee() { Id = System.Guid.NewGuid().ToString(), Name = "李四", Sex = "", ParentId = emp1.Id };
                //插入员工
                emp1.Save();
                emp2.Save();
    
                //取员工的上级
                var emp2Parent = emp2.Parent;
                var emp2Parent_Parent = emp2Parent.Parent;
    
                //删除员工
                emp2.Drop();
                emp1.Drop();
            }
        }
    View Code

    总结:

      从两者Service层和BLL 层的代码区分来看,两者都是实现了业务功能和延迟加载。

    贫血模型优点是系统的层次结构清楚,各层之间单向依赖。缺点是不够面向对象。

    充血模型优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。缺点是比较复杂,对技术要求更高。

    对于web开发,个人推荐用贫血模型。其实无论是采用哪种模型,都是可以的,只不过作为我们自己,要真正去理解为什么要这么做,以及怎样去解决问题,而不是学到一知半解,把两种方式混用,分出DAL 层来,却又采用充血模型去操作,然后又去遵循贫血模型的规范,把代码写的乱七八糟,层不是层(吐槽一下,在这样的项目里,让我很难受)。

    好的代码,应该是简单的,应该是美的,应该是能解决问题而不是制造问题的,不要为了面向对象而面向对象。

    以上都是我的个人理解,有不对的地方,欢迎大家指正。

    ps:最近在做项目,发现有人在贫血模型中使用Parent类似的这种类,但是又不能解决延时加载的问题,或者是每次用的时候都要再加载,没有添加Parent的意义,反而导致这些对象不能及时回收,心有所感,所以在这里总结一下,与大家分享。

  • 相关阅读:
    使用 C# 2008 Express Edition 编写的猜数字游戏
    话说三层
    在asp.net 1.1 中使用Ajax
    vs2005 调试时出现“无法附加。绑定句柄无效”的解决办法
    解决“你可能没有权限使用网络资源”的问题
    html&js 在firefox与IE中呈现存在差异的解决方法总结
    sql 事务 全攻略
    mssql的TSQL教程(从建登陆到建库、表和约束)(1)
    数据库练习题
    用批处理附加数据库
  • 原文地址:https://www.cnblogs.com/NewBigLiang/p/4971513.html
Copyright © 2011-2022 走看看