持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
场景:
- 在权限控制的场景中,我们经常会有多条件流程的判断,权限1满足,进行判断权限2,满足权限2,继续判断权限3,这样持续权限判断
- 某系统的审批流程,组长、主管、经理、总经理,一层一层审批
普通方式实现
如果不使用设计模式时,每增加一个条件可能就需要增加权限判断,就会导致代码臃肿且维护性差。比如实现方式如下:
package pkg
type DealHandler interface {
handler() bool
}
type ADeal struct {
name string
}
func (adel *ADeal) handler() bool {
println(adel.name + "A 审批")
return true
}
type BDeal struct {
name string
}
func (bdel *BDeal) handler() bool {
println(bdel.name + "B 审批")
return true
}
type CDeal struct {
name string
}
func (cdel *CDeal) handler() bool {
println(cdel.name + "c 审批")
return true
}
func MainDeal() {
AAA := ADeal{"我是A"}
BBB := BDeal{"我是B"}
CCC := CDeal{"我是C"}
if AAA.handler() {
if BBB.handler() {
if CCC.handler() {
println("都处理完成")
}
}
}
}
你会发现,如果有100个审批的,你可能就会写100个 if 判断,整个代码就很冗余,如果需要去掉或者增加审批都会对代码改动很大,且有很大的风险。
优化改造
进一步优化下代码,我们可以通过每次审批时就开始判断下一次是否审批,互相关联形成一条链。
type IDuty interface {
Handler()
}
type ADuty struct {
Name string
BDuty *BDuty
}
func (aduty *ADuty) dispaly() bool {
return true
}
func (aduty *ADuty) Handler() {
if aduty.dispaly() {
println("我是" + aduty.Name + "我完成工作")
aduty.BDuty.Handler()
}
}
type BDuty struct {
Name string
CDuty *CDuty
}
func (bduty *BDuty) dispaly() bool {
return true
}
func (bduty *BDuty) Handler() {
if bduty.dispaly() {
println("我是" + bduty.Name + "我完成工作")
bduty.CDuty.Handler()
}
}
type CDuty struct {
Name string
DDuty *interface{}
}
func (cduty *CDuty) dispaly() bool {
return true
}
func (cduty *CDuty) Handler() {
if cduty.dispaly() {
println("我是" + cduty.Name + "我完成工作")
println("任务结束")
}
}
func main() {
cduty := pattern.CDuty{"cc", nil}
bduty := pattern.BDuty{"BB", &cduty}
aduty := pattern.ADuty{"AA", &bduty}
aduty.Handler()
}
每个责任实例中包含下一个责任实例,再根据其 display 方法取判断是否进行下一个责任实例。但这样写法适合的场景是,每个责任都是明确的,形成一个固定的链接,代码扩展也不好。
责任链模式
type IDuty interface {
SetNext(nextDuty IDuty) IDuty //设置下一个业务
Do() // 自身的业务
Handler() //执行
}
type DutyClass struct {
Name string
Next IDuty
}
func (aduty *DutyClass) Do() {
if isDeal {
// ---处理自身业务
}
}
func (aduty *DutyClass) SetNext(nextDuty IDuty) IDuty {
aduty.Name = ""
aduty.Next = nextDuty
return nextDuty
}
func (aduty *DutyClass) Handler() {
println(aduty.Name + "处理")
aduty.Next.Do()
if aduty.Next != nil {
aduty.Next.Handler()
}
}
type ADuty struct {
DutyClass
}
func (h *ADuty) Do() (err error) {
fmt.Println("我是AAA处理...")
return
}
type BDuty struct {
DutyClass
}
func (h *BDuty) Do() (err error) {
fmt.Println("我是 BBB 处理...")
return
}
type CDuty struct {
DutyClass
}
func (h *CDuty) Do() (err error) {
fmt.Println("我是 CCC 处理...")
return
}
func main(){
firstDuty := &pattern.DutyClass{}
firstDuty.SetNext(&pattern.ADuty{}).SetNext(&pattern.BDuty{}).SetNext(&pattern.CDuty{})
firstDuty.Handler()
println("执行结束")
}
- 定义一个处理请求的接口 IDuty, 里面包含 包含抽象处理方法和一个后继连接。
- 定义个具体的处理者,实现接口的方法,并且在 handler 方法中判断是否处理本次请求,不处理则转到后续处理者
- 定义多个具体的处理对象,每个处理对象都是针对专门的业务划分
责任链的基本组成:
- 抽象处理者(Handler)角色
- 具体处理者(Concrete Handler)角色
- 客户类(Client)角色
参考资料: