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的意义,反而导致这些对象不能及时回收,心有所感,所以在这里总结一下,与大家分享。

  • 相关阅读:
    函数
    python操作文件
    POJ-2689-Prime Distance(素数区间筛法)
    POJ-2891-Strange Way to Express Integers(线性同余方程组)
    POJ-2142-The Balance
    POJ-1061-青蛙的约会(扩展欧几里得)
    Educational Codeforces Round 75 (Rated for Div. 2) D. Salary Changing
    Educational Codeforces Round 75 (Rated for Div. 2) C. Minimize The Integer
    Educational Codeforces Round 75 (Rated for Div. 2) B. Binary Palindromes
    Educational Codeforces Round 75 (Rated for Div. 2) A. Broken Keyboard
  • 原文地址:https://www.cnblogs.com/NewBigLiang/p/4971513.html
Copyright © 2011-2022 走看看