Golang - 使用责任链模式代替IF ELSE

一、传统 IF 判断

1、在业务中使用大量的 if 判断

代码如下:

package main

type SellInfo struct {
    Price      float64
    OrderCount int
    TotalCount int
    MemberShip int
}

func main2() {
    var a = SellInfo{
        Price:      1.0,
        OrderCount: 1,
        TotalCount: 20,
        MemberShip: 1,
    }
    if a.Price > 0 {
        println("true")
    }
    if a.TotalCount > a.OrderCount {
        println("true")
    }
    if a.MemberShip == 1 {
        println("true")
    }
    if a.Price < 100 && a.MemberShip == 2 {
        println("true")
    }
}

2、如果再继续添加新的条件?

在上面的代码中,如果业务又需要增加新的判断,继续添加if条件?这可能是无限if下去的无底洞?

if判断对cpu还是很消耗资源的(搜索:cpu对if分支判断),引入今天的主角:责任链。

责任链的思路:将一个复杂逻辑的流程进行分解,将每个判断条件的判断交给责任链节点进行处理,在处理完成后将结果传递给下一个节点。

二、责任链 KILL IF

1、正确使用接口与对象

代码如下:

package main

import "fmt"

type SomeConditions struct {
    Price      float64
    OrderCount int
    TotalCount int
    MemberShip int
}

type Rule interface {
    Check(s *SomeConditions) bool
}

type PriceCheck struct{}

func (p *PriceCheck) Check(s *SomeConditions) bool {
    return s.Price > 0
}

这里定义了一个Rule的接口类型
接口: 在Go语言中接口(interface)是一种类型,一种抽象的类型

上面代码可以看到,有一个比较有意思的地方,就是使用了空结构体

type PriceCheck struct{}

然后在这个结构体上再追加一个实现接口的方法

func (p *PriceCheck) Check(s *SomeConditions) bool { }

2、go责任链核心代码

注意:这里需要判断业务的整体性,如果都是false,要求为true抛出返回,则需要更改如下代码

判断的整体业务是以true为基本,一旦发生false则抛出返回的原则
如下代码:

// 聚合所有条件
func chain(s *SomeConditions, rules ...Rule) bool {
    for _, rule := range rules {
        if !rule.Check(s) {
            return false
        }
    }
    return true
}

3、go责任链完整代码

以下实现了设计原则:

package main

import "fmt"

type SomeConditions struct {
    Price      float64
    OrderCount int
    TotalCount int
    MemberShip int
}

type Rule interface {
    Check(s *SomeConditions) bool
}

// 聚合所有条件
func chain(s *SomeConditions, rules ...Rule) bool {
    for _, rule := range rules {
        if !rule.Check(s) {
            return false
        }
    }
    return true
}

func main() {
    SomeConditions := &SomeConditions{
        Price:      1.00,
        OrderCount: 2,
        TotalCount: 10,
        MemberShip: 2,
    }
    rules := []Rule{
        &PriceCheck{},
        &OrderCountCheck{},
        &MemberShipCheck{},
        &DiscountCheck{},
    }

    flag := chain(SomeConditions, rules...)
    fmt.Println(flag)
}

type PriceCheck struct{}

func (p *PriceCheck) Check(s *SomeConditions) bool {
    return s.Price > 0
}

type OrderCountCheck struct{}

func (o *OrderCountCheck) Check(s *SomeConditions) bool {
    return s.TotalCount > s.OrderCount
}

type MemberShipCheck struct{}

func (m *MemberShipCheck) Check(s *SomeConditions) bool {
    return s.MemberShip == 2
}

type DiscountCheck struct{}

func (d *DiscountCheck) Check(s *SomeConditions) bool {

    return s.Price > 10 && s.MemberShip == 2
}

 

posted @ 2024-07-14 20:27  李若盛开  阅读(84)  评论(0)    收藏  举报