当前位置: 首页 > news >正文

代码开发,常用的几种设计模式【golang】

一、创建型模式(处理对象创建)

1. 单例模式(Singleton)

用途:保证一个结构体在程序运行期间只有一个实例(确保全局只有一个实例被new出来),并提供全局访问点(如配置管理器、日志器)

Go 实现特点:利用 sync.Once 保证线程安全,是 Go 中最优雅的单例实现方式

读取配置文件案例

var(instance*Config once sync.Once)funcGetConfig()*Config{once.Do(func(){instance=&Config{Port:8080}})returninstance}
2. 工厂模式(Factory)

用途:封装对象创建逻辑,根据不同条件返回不同的结构体实例

Go 实现特点:通常用函数返回接口。

获取不同类型数据库链接句柄

typeDBinterface{Query(string)string}typeMySQLstruct{}func(m MySQL)Query(qstring)string{return"MySQL: "+q}typePgSQLstruct{}func(m PgSQL)Query(qstring)string{return"PgSQL: "+q}// 工厂函数funcNewDB(dbTypestring)DB{switchdbType{case"mysql":returnMySQL{}case"pgsql":returnPgSQL{}default:panic("unsupported db")}}

二、结构型模式(处理对象组合)

1. 装饰器模式(Decorator)

装饰器模式(Decorator Pattern)是一种结构型设计模式,核心目标是:在不修改原有对象代码的前提下,动态地给对象添加额外的功能。

用途:动态添加功能(如日志、限流、认证)

Go 实现特点:体现有多种,如函数嵌套、组合 + 接口方式继承重写方法等

标准库http服务实现案例

funcmain(){http.HandleFunc("/api",myHandler)http.ListenAndServe(":8080",nil)}// 业务逻辑funcmyHandler(w http.ResponseWriter,r*http.Request){w.WriteHeader(http.StatusOK)w.Write([]byte("Hello from decorated handler!"))// ……}

这是标准库的内置方法,http.HandleFunc定义为func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

现在我要给我的业务逻辑方法加个日志,又不想改动其代码,现在给它包裹上一层

funcmain(){handler:=withLogging(myHandler)http.HandleFunc("/api",handler)http.ListenAndServe(":8080",nil)}funcwithLogging(next http.HandlerFunc)http.HandlerFunc{returnfunc(w http.ResponseWriter,r*http.Request){log.Printf("Received request: %s %s",r.Method,r.URL.Path)next(w,r)// 这里是业务逻辑方法}}// 业务逻辑funcmyHandler(w http.ResponseWriter,r*http.Request){w.WriteHeader(http.StatusOK)w.Write([]byte("Hello from decorated handler!"))}

通过重新定义一个闭包函数,加点日志代码,对其原有业务逻辑进行装饰

另一种继承式写法,计算咖啡价格

// 咖啡typeCoffeeinterface{Cost()int// 价格}// 接口实现:咖啡价格typeBlackCoffeestruct{}func(b*BlackCoffee)Cost()int{return10}// 装饰器1:咖啡加牛奶的价格typeMilkDecoratorstruct{coffee Coffee// 嵌套咖啡接口}func(m*MilkDecorator)Cost()int{returnm.coffee.Cost()+2// 基础价格+牛奶价格}// 传入实现Coffee接口的实例,返回另一个实现Coffee接口的实例funcNewMilkDecorator(coffee Coffee)Coffee{return&MilkDecorator{coffee:coffee}}funcmain(){// 基础黑咖啡coffee:=&BlackCoffee{}fmt.Printf("价格:%d\n",coffee.Cost())// 价格:10// 加牛奶(装饰)coffeeWithMilk:=NewMilkDecorator(coffee)fmt.Printf("价格:%d\n",coffeeWithMilk.Cost())// 黑咖啡 + 牛奶, 价格:12}
2. 适配器模式(Adapter)

用途:将一个结构体的接口转换成客户端期望的另一个接口,解决接口不兼容问题

Go 实现特点:适配器结构体嵌套原结构体,实现目标接口

继承老的业务逻辑,新增新的接口实现

// 旧的代码定义typeOldhandlestruct{}func(a*Oldhandle)SpecificRequest()string{return"旧接口的具体实现"}// 现在感觉 SpecificRequest 名字不好听,改成 Request// 希望的接口定义typeTargetinterface{Request()string}// 适配器:将 Oldhandle 适配为Target接口typeNewHandlestruct{Oldhandle*Oldhandle}// 实现 Target 接口,内部调用 Oldhandle 的方法func(a*NewHandle)Request()string{return"适配后:"+a.Oldhandle.SpecificRequest()}funcmain(){// 客户端只依赖 Target 接口,无需关心 Oldhandle 的具体实现vartarget Target=&NewHandle{Oldhandle:&Oldhandle{}}target.Request()// 输出: 适配后:旧接口的具体实现}

装饰器与适配器非常类似,几乎没什么不同,通过类型嵌套方式继承功能并改造

三、行为型模式(处理对象交互)

1. 策略模式(Strategy)

用途:定义一系列算法,将每个算法封装起来并可互相替换,使算法独立于使用它的客户端(如支付方式、排序算法切换)。

Go 实现特点:通过接口定义算法行为,不同策略实现该接口,客户端动态切换策略。

微信支付、支付宝支付,业务逻辑选择

// 1. 支付接口定义(策略定义)typePayInterinterface{Pay(amountfloat64)string// 输入金额,返回支付结果}// 2. 策略可选列表// 2.1 支付宝typeAlipaystruct{}func(a Alipay)Pay(amountfloat64)string{returnfmt.Sprintf("Paid %.2f via Alipay",amount)}// 2.2 微信支付typeWechatPaystruct{}func(w WechatPay)Pay(amountfloat64)string{returnfmt.Sprintf("Paid %.2f via WeChat",amount)}// 3. 策略执行// 购物车支付场景typeShoppingCartstruct{payMethod PayInter}// 设置购物车支付场景用哪种方式支付func(cart*ShoppingCart)SetPayMethod(method PayInter){cart.payMethod=method}// 执行支付func(cart*ShoppingCart)Checkout(amountfloat64)string{ifcart.payMethod==nil{return"No payment method set"}returncart.payMethod.Pay(amount)}funcmain(){cart:=&ShoppingCart{}cart.SetPayMethod(Alipay{})fmt.Println(cart.Checkout(99.9))// Paid 99.90 via Alipaycart.SetPayMethod(WechatPay{})fmt.Println(cart.Checkout(199.0))// Paid 199.00 via WeChat}

这种方式本质上还是结构体嵌套,继承

2. 选项模式

用途:优雅地设置可选参数(替代构造函数重载)

广泛用于代码量大的类库封装(如 http.Server, grpc.DialOption)

初始化一个结构体示例

typeServerstruct{PortintTimeout time.Duration}funcNewServer(portint,timeout time.Duration)*Server{return&Server{Port:port,Timeout:timeout,}}funcTestManual(t*testing.T){server:=NewServer(3000,5*time.Second)t.Log(server.Port)}

通过NewServer方法初始化Server结构,Server的参数有十几个,NewServer里面的参数定义要写很多,不美观,比方说

NewServer(port int, timeout time.Duration, worker int)我现在调用NewServer方法时,只想设置portworker参数,中间这个参数我还得想办法传递个零值或默认值进去,不然代码会报错

现在换一种写法,通过增加代码量来提升维护性

typeServerstruct{PortintTimeout time.Duration}typeOptionfunc(*Server)funcWithPort(portint)Option{returnfunc(s*Server){s.Port=port}}funcWithTimeout(t time.Duration)Option{returnfunc(s*Server){s.Timeout=t}}funcNewServer(opts...Option)*Server{s:=&Server{Port:8080}for_,opt:=rangeopts{opt(s)}returns}// 业务逻辑funcTestManual(t*testing.T){server:=NewServer(WithPort(3000),WithTimeout(5*time.Second))t.Log(server.Port)}

现在调用NewServer方法时,想自定义哪个参数,就传递指定配置方法即可,也不用操心顺序,反正是个切片类型

四、管道/过滤器模式(Pipeline / Filter)

用途:通过 channel 串联处理步骤(典型 Go 并发模式)

基于 goroutine + channel

我习惯称之为一个小的MapReduce实现

// 这里生产数据,预处理funcgen(nums...int)<-chanint{out:=make(chanint)gofunc(){for_,n:=rangenums{out<-n}close(out)}()returnout}// 这里加工数据funcsq(in<-chanint)<-chanint{out:=make(chanint)gofunc(){forn:=rangein{out<-n*n}close(out)}()returnout}// 这里通过range读取chan展示数据funcmain(){forn:=rangesq(gen(1,2,3)){fmt.Println(n)}}

剩下的还有观察者模式等等一大堆写法,总的来说无非都是闭包、结构体继承、chan读写等……

http://www.cnnetsun.cn/news/66306.html

相关文章:

  • SMDJ45A单向 TVS瞬态抑制二极管 :3000W浪涌保护管 防雷击抗静电
  • Foundation 文本
  • Sui 主网升级至 V1.61.2
  • 25、Kubernetes 应用部署与管理实践
  • 31、容器化应用设计理念与实践
  • 如何评估LobeChat的加载速度与响应延迟?性能基准测试
  • 缓存与数据库一致性解决方案深度解析
  • 消息队列真仙:我的道念支持最终一致性
  • Spring Boot项目推送Gitee全流程(进阶)
  • Java毕设项目:基于Springboot大学校园自习室教室座位预约网站设计与实现基于springboot高校自习室预约系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • JAVA打造同城羽馆预约,一键畅享运动
  • 经验贴 | 科学制定招聘需求与预算:HR 必看的逻辑与实操要点
  • 经验贴 | AI 面试评估系统怎么用?HR 高效识人实操指南
  • 构建个性化AI助手:LobeChat会话管理功能深度使用技巧
  • 基于昇腾NPU的YOLOV8-seg c++部署
  • 26、深入探索脚本编程与系统安全基础
  • XSS漏洞有哪几种?DOM型XSS和反射型有什么区别?SQL注入原理又是什么?网安面试题常见问题一文详解
  • 压力扫描阀:并行校准技术,解锁多点压力测量新高度
  • PyTorch框架下运行Qwen3-32B的内存优化策略
  • 为什么说Qwen3-8B是学术研究的理想选择?实测报告出炉
  • java基础-PriorityQueue(优先队列)
  • Qwen3-14B模型量化压缩技术:降低GPU内存占用
  • 18、日期和时间的格式化、解析及时间区域的使用
  • VisionPro CogIPOneImageTool1 工具超详细解释(含内部功能全解析)
  • VisionPro CogIDTool 工具超深度详解(技术细节 + 实战配置版)
  • 让 BI 拥有‘领域大脑’:智能 BI 如何实现 AI 级精准数据查询
  • 提示工程架构师的战略规划:提示系统生命周期管理
  • 条形码识别与定位:基于FCOS框架的多类型条码检测与识别技术详解
  • AutoGPT能否用于学术文献综述?研究辅助工具测评
  • 如何用AutoGPT实现任务全自动执行?深度解析开源大模型能力