貧血模型和充血模型


一、貧血模型

所謂貧血模型,是指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的意義,反而導致這些對象不能及時回收,心有所感,所以在這里總結一下,與大家分享。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM