[go] 模版方法模式

简介: [go] 模版方法模式

模版方法模式


在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。


模型说明



  • AbstractClass: 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为抽象类型, 也可以提供一些默认实现。
  • ConcreteClass: 可以重写所有步骤, 但不能重写模板方法自身。


优缺点


1.优点

  • 你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
  • 你可将重复代码提取到一个超类中。


2.缺点


  • 部分客户端可能会受到算法框架的限制。
  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则
  • 模板方法中的步骤越多, 其维护工作就可能会越困难。


使用场景


  • 当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
  • 当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。


参考代码


比如说我们需要给用户发送验证码,通过 sms、email 的方式。其具体的流程都是相同的:

  1. 生成随机的 n 位数字。
  2. 在缓存中保存这组数字以便进行后续验证。
  3. 准备内容。
  4. 发送通知。


// otp.go 模板方法
package main
type IOtp interface {
 genRandomOTP(int) string
 saveOTPCache(string)
 getMessage(string) string
 sendNotification(string) error
}
type Otp struct {
 iOtp IOtp
}
func (o *Otp) genAndSendOTP(otpLength int) error {
 otp := o.iOtp.genRandomOTP(otpLength)
 o.iOtp.saveOTPCache(otp)
 message := o.iOtp.getMessage(otp)
 err := o.iOtp.sendNotification(message)
 if err != nil {
  return err
 }
 return nil
}
// sms.go 具体实现类
package main
import "fmt"
type Sms struct {
 Otp
}
func (s *Sms) genRandomOTP(len int) string {
 randomOTP := "1234"
 fmt.Printf("SMS: generating random otp %s\n", randomOTP)
 return randomOTP
}
func (s *Sms) saveOTPCache(otp string) {
 fmt.Printf("SMS: saving otp: %s to cache\n", otp)
}
func (s *Sms) getMessage(otp string) string {
 return "SMS OTP for login is " + otp
}
func (s *Sms) sendNotification(message string) error {
 fmt.Printf("SMS: sending sms: %s\n", message)
 return nil
}
// email.go 具体实现类
package main
import "fmt"
type Email struct {
 Otp
}
func (s *Email) genRandomOTP(len int) string {
 randomOTP := "1234"
 fmt.Printf("EMAIL: generating random otp %s\n", randomOTP)
 return randomOTP
}
func (s *Email) saveOTPCache(otp string) {
 fmt.Printf("EMAIL: saving otp: %s to cache\n", otp)
}
func (s *Email) getMessage(otp string) string {
 return "EMAIL OTP for login is " + otp
}
func (s *Email) sendNotification(message string) error {
 fmt.Printf("EMAIL: sending email: %s\n", message)
 return nil
}
// main.go 客户端
package main
import "fmt"
func main() {
 smsOTP := &Sms{}
 o := Otp{
  iOtp: smsOTP,
 }
 o.genAndSendOTP(4)
 fmt.Println("")
 emailOTP := &Email{}
 o = Otp{
  iOtp: emailOTP,
 }
 o.genAndSendOTP(4)
}


output:


SMS: generating random otp 1234
SMS: saving otp: 1234 to cache
SMS: sending sms: SMS OTP for login is 1234
EMAIL: generating random otp 1234
EMAIL: saving otp: 1234 to cache
EMAIL: sending email: EMAIL OTP for login is 1234

相关文章
|
人工智能 安全 算法
Go入门实战:并发模式的使用
本文详细探讨了Go语言的并发模式,包括Goroutine、Channel、Mutex和WaitGroup等核心概念。通过具体代码实例与详细解释,介绍了这些模式的原理及应用。同时分析了未来发展趋势与挑战,如更高效的并发控制、更好的并发安全及性能优化。Go语言凭借其优秀的并发性能,在现代编程中备受青睐。
512 33
|
10月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
450 2
Go语言方法与接收者 -《Go语言实战指南》
本文介绍了 Go 语言中方法的相关概念和用法。方法是绑定到特定类型上的函数,包含值接收者和指针接收者两种形式。值接收者不会改变原始数据,而指针接收者可修改原始数据,且在处理大型结构体时性能更优。文章详细对比了方法与普通函数的区别,并说明了选择指针接收者的原因,如修改原始值、提升性能及保持一致性。此外,Go 支持为任意自定义类型定义方法,不仅限于结构体。最后通过表格总结了方法的核心概念和使用场景。
369 34
|
缓存 NoSQL Go
通过 SingleFlight 模式学习 Go 并发编程
通过 SingleFlight 模式学习 Go 并发编程
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
SQL 关系型数据库 MySQL
Go语言项目高效对接SQL数据库:实践技巧与方法
在Go语言项目中,与SQL数据库进行对接是一项基础且重要的任务
436 11
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
大数据 Shell Go
GO方法与自定义类型
本文详细介绍了 Go 语言中的自定义数据类型与方法。不同于传统的面向对象编程语言,Go 通过结构体 (`struct`) 和方法 (`method`) 来扩展自定义类型的功能。文章解释了如何定义结构体、创建方法,并探讨了值接收器与指针接收器的区别及应用场景。此外,还介绍了方法的可见性以及接收器的命名惯例。通过具体示例,帮助读者更好地理解和应用这些概念。
275 2
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式

热门文章

最新文章