贫血模型
所谓贫血模型,是指Model 中,仅包含状态(属性),不包含行为(方法),采用这种设计时,需要分离出DB层,专门用于数据库操作(数据库作为状态)。
简单例子
对于员工Employee来说,每个员工的属性有Id,Name,Sex,BirthDay,Parent(上级),行为有查找,保存,删除,职位调整(更换上级) 等
采用贫血模型实现
// Model层
package entity
import (
"time"
)
type Employee struct {
Id uint `json:"id"`
Name string `json:"name"`
Sex string `json:"sex"`
Birthday time.Time `json:"birthday"`
ParentId uint `json:"parent_id"`
}
// dao层
package dao
import (
"trash/entity"
)
type EmpDAO struct {
}
// 添加员工,实现方法略
func (p *EmpDAO) AddEmployee(emp *entity.Employee) int64 {
return 1
}
// 更新员工,实现方法略
func (p *EmpDAO) UpdateEmployee(emp *entity.Employee) int64 {
return 1
}
// 删除员工,实现方法略
func (p *EmpDAO) DeleteEmployee(emp *entity.Employee) int64 {
return 1
}
// 获取员工,实现方法略
func (p *EmpDAO) GetEmployeeById(id uint) entity.Employee {
var emp entity.Employee
emp.Id = uint(1)
emp.Name = "张三"
return emp
}
// service层
package service
import (
"fmt"
"time"
"trash/dao"
"trash/entity"
)
type EmpService struct {
}
var empdao = new(dao.EmpDAO)
func (p *EmpService) Test() {
//转化所需模板
timeLayout := "2020-01-02"
//重要:获取时区
loc, _ := time.LoadLocation("Local")
//使用模板在对应时区转化为time.time类型
var emp1 = new(entity.Employee)
emp1.Id = uint(1)
emp1.Name = "张三"
emp1.Sex = "男"
birthday1, _ := time.ParseInLocation(timeLayout, "1990-08-25", loc)
emp1.Birthday = birthday1
var emp2 = new(entity.Employee)
emp2.Id = uint(2)
emp2.Name = "李四"
emp2.Sex = "男"
emp2.ParentId = emp1.Id
birthday2, _ := time.ParseInLocation(timeLayout, "1995-01-25", loc)
emp2.Birthday = birthday2
empdao.AddEmployee(emp1)
empdao.AddEmployee(emp2)
// 获取员工上级
var emp2Parent = empdao.GetEmployeeById(emp2.ParentId)
fmt.Print(emp2Parent)
// 删除员工信息
empdao.DeleteEmployee(emp1)
}
充血模型
Model 中既包括状态,又包括行为,是最符合面向对象的设计方式。
简单例子
若采用充血模型设计,则应只分两层 ,Model 层(包含状态和行为)和Service(BLL) 层
// Model 层
package entity
import (
"time"
)
type Employee struct {
Id uint `json:"id"`
Name string `json:"name"`
Sex string `json:"sex"`
Birthday time.Time `json:"birthday"`
ParentId uint `json:"parent_id"`
Parent *Employee
}
// 保存员工,实现方法略
func (p *Employee) Save() int64 {
return 1
}
// 删除员工,实现方法略
func (p *Employee) Drop() int64 {
return 1
}
// 获取员工,实现方法略
func (p *Employee) Query(id uint) Employee {
var emp Employee
emp.Id = id
return emp
}
func (p *Employee) GetParent() *Employee {
if p.Parent != nil {
return p.Parent
} else {
var p = new(Employee)
p.Id = uint(1)
p.Name = "张三"
p.Sex = "男"
return p
}
}
// Service(BLL)层
package service
import (
"fmt"
"time"
"trash/entity"
)
type EmpService struct {
}
func (p *EmpService) Test() {
//转化所需模板
timeLayout := "2020-01-02"
//重要:获取时区
loc, _ := time.LoadLocation("Local")
//使用模板在对应时区转化为time.time类型
var emp1 = new(entity.Employee)
emp1.Id = uint(1)
emp1.Name = "张三"
emp1.Sex = "男"
birthday1, _ := time.ParseInLocation(timeLayout, "1990-08-25", loc)
emp1.Birthday = birthday1
var emp2 = new(entity.Employee)
emp2.Id = uint(2)
emp2.Name = "李四"
emp2.Sex = "男"
emp2.ParentId = emp1.Id
birthday2, _ := time.ParseInLocation(timeLayout, "1995-01-25", loc)
emp2.Birthday = birthday2
emp1.Save()
emp2.Save()
// 获取员工上级
var emp2Parent = emp2.GetParent()
fmt.Print(emp2Parent)
// 删除员工信息
emp1.Drop()
emp2.Drop()
}
总结
从两者Service层和BLL 层的代码区分来看,两者都是实现了业务功能和延迟加载。
贫血模型优点是系统的层次结构清楚,各层之间单向依赖。缺点是不够面向对象。充血模型优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。缺点是比较复杂,对技术要求更高。
以上都是我阅读他人文章做的笔记,有遗漏或者不对的地方,欢迎大家指正。