首页 > 其他分享 >Golang - 使用责任链模式代替IF ELSE

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

时间:2024-07-14 20:29:49浏览次数:17  
标签:SomeConditions Price ELSE Golang 代替 func bool type Check

一、传统 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
}

 

标签:SomeConditions,Price,ELSE,Golang,代替,func,bool,type,Check
From: https://www.cnblogs.com/beatle-go/p/17974695

相关文章

  • 分支预测,为什么使用 if/else 语句会降低程序效率
    在现代CPU架构中,分支预测是为了提高指令执行的效率。然而,如果if/else语句的分支走向难以预测,就可能会降低程序效率。这是因为当CPU执行到 if/else 语句时,它需要猜测接下来要执行的是if 分支还是else 分支。如果CPU的预测错误,就需要清空已经预取和执行的部分指令,重新......
  • golang channel 的众多应用场景123
    目录1.应用场景2.应用场景示例2.1并发控制2.2管道|范围迭代|数据传输2.3数据传递->生产者-消费者模型2.4互斥同步2.5信号通知2.6定时器我们知道go中有个很重要的数据结构叫做channel-通道,通过其特性,我们可以完成很多功能,自然就对应到很多应用场景了。1.应用场景......
  • SQL中的case when then else end用法
    Case具有两种格式。简单Case函数和Case搜索函数。1--简单Case函数2CASEsex3WHEN'1'THEN'男'4WHEN'2'THEN'女'5ELSE'其他'END6--Case搜索函数7CASEWHENsex='1'THEN'男'8W......
  • 显卡欺骗器、锁屏宝的代替品,ToDesk虚拟屏功能完美解决
    主机没有显示器?远控电脑需要保持屏幕的高分辨率,但过高容易黑屏?遇到以上情况,人们常常会使用显卡欺骗器或者锁屏宝来解决,就是让显卡认为连接了一个显示器,方便正常使用电脑。但是这往往需要额外给电脑上插入设备,如果是突然急用就很难实现了,有没有人帮忙装显卡欺骗器不说,临时买不买......
  • Java性能优化-switch-case和if-else速度性能对比,到底谁快?
    场景Java中使用JMH(JavaMicrobenchmarkHarness微基准测试框架)进行性能测试和优化:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131723751参考以上性能测试工具的使用。下面针对Java中对switch-case和if-else在速度方面的性能做测试。注:博客:https://blog......
  • golang 接口按需获取资源
    场景爬虫业务场景,我们需要调用三方接口获取代理ip地址,每个ip地址可以使用的时间有限和价格的,本着不浪费资源,我们在这里做一层封装。当有其他业务调用我们接口的时候,会拉起定时任务,这个定时任务的生命周期为5分钟,超过5分钟这个定时任务就会停止,每一次请求时都会更新定时生命周期......
  • golang sync.Pool 的基本原理
    sync.Pool包寥寥不过300行代码,却可以为我们提供类似对象池的功能,减少了对象的重复创建于销毁,减少了性能损耗,增加内存复用,同时自带mutex锁可以保证Put/Get操作的并发安全特性,在一些对象需要重复创建销毁的场景中很是实用,今天来看看sync.Pool的基本原理。sync.Pool就在标准......
  • 基于bootstrap与jQuery实现的分页功能(多余部分省略号代替)
    基于bootstrap与jQuery实现的分页功能(多余部分省略号代替) <navaria-label='Pagenavigation'id='nav_navigation'></nav><scripttype='text/javascript'>/***刷新页码方法*@paramtotalPage*@paramcurrentPage*/functionrefres......
  • golang 操作es
    docker 操作安装es 1.创建网络因为我们还需要部署kibana容器,因此需要让es和kibana容器互联,这里先创建一个网络。使用FinalShell登录自己的Linux云服务器客户端(阿里云或腾讯云)dockernetworkcreatees-net2.加载镜像 dockerpulldocker.elastic.co/elasticsearc......
  • Golang 切片作为函数参数传递的陷阱与解答
    作者:林冠宏/指尖下的幽灵。转载者,请:务必标明出处。GitHub:https://github.com/af913337456/出版的书籍:《1.0-区块链DApp开发实战》《2.0-区块链DApp开发:基于公链》例子切片作为函数参数传递的是值用来误导切片作为函数参数传递的是引用函数内切片append引起......