模板方法设计模式是一种行为型设计模式。这种模式通过常用于为某种特定的操作定义一个模板或者算法模型。

以一次性密码(OTP:One Time Password)为例。我们常见的一次性密码有两种:短信密码(SMS OTP)或者邮件密码(Email OTP)。不过不管是短信密码还是邮件密码,它们的处理步骤都是一样的,步骤如下:

  1. 生成一串随机字符串
  2. 将字符串保存进缓存用来执行后续的验证
  3. 准备通知内容
  4. 发送通知
  5. 记录统计信息

在以上的步骤中,除了第4项“发送通知”的具体方式不一样,其他步骤都是不变的。即使以后有了新的一次性密码发送方式,可以预见以上的步骤也是不变的。

在这类场景中,即一个操作的步骤是固定的,只是在具体的执行方式上存在差异,这时我们就可以用到模板方法模式了。在模板方法模式中,我们通常会为这个操作定义一个模板接口或算法模型接口,接口中包含固定方法,然后由具体的实现类来重写相关接口并实现这些操作。

下面是一次性密码这个例子的实现:

otp.go

type iOtp interface {
genRandomOTP(int) string
saveOTPCache(string)
getMessage(string) string
sendNotification(string) error
publishMetric()
} 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
}
o.iOtp.publishMetric()
return nil
}

简单解读下这段代码:

  • 在上面的代码中定义了iOtp接口,这个接口中的方法即OTP所需的相关步骤
  • 下面的smsemailiOtp接口的实现
  • 在结构体otp中定义了模板方法genAndSendOTP()

此外注意下:在上面这段代码中将iOtp接口和结构体otp合在了一起,提供了类似于抽象类的实现,这种做法大家需要的时候可以借鉴下。

sms.go

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
} func (s *sms) publishMetric() {
fmt.Printf("SMS: publishing metrics\n")
}

email.go

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
} func (s *email) publishMetric() {
fmt.Printf("EMAIL: publishing metrics\n")
}

main.go

import "fmt"

func main() {
smsOTP := &sms{}
o := otp{
iOtp: smsOTP,
}
o.genAndSendOTP(4)
fmt.Println("")
emailOTP := &email{}
o = otp{
iOtp: emailOTP,
}
o.genAndSendOTP(4)
}

输出内容为:

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

代码已上传至GitHub: zhyea / go-patterns / template-method-pattern

END!!

GoLang设计模式16 - 模板方法模式的更多相关文章

  1. 乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern)

    原文:乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 模板方法模式(Template Method ...

  2. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

  3. Golang设计模式—简单工厂模式(Simple Factory Pattern)

    Golang设计模式--简单工厂模式 背景 假设我们在做一款小型翻译软件,软件可以将德语.英语.日语都翻译成目标中文,并显示在前端. 思路 我们会有三个具体的语言翻译结构体,或许以后还有更多,但现在分 ...

  4. js设计模式——6.模板方法模式与职责链模式

    js设计模式——6.模板方法模式与职责链模式 职责链模式

  5. java设计模式之模板方法模式

    模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.通俗的说的就是有很多相同的步骤的,在某一些地方可能有一些差 ...

  6. C#设计模式(14)——模板方法模式(Template Method)

    一.引言 提到模板,大家肯定不免想到生活中的“简历模板”.“论文模板”.“Word中模版文件”等,在现实生活中,模板的概念就是——有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简 ...

  7. 【GOF23设计模式】模板方法模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_模板方法模式.钩子函数.方法回调.好莱坞原则 package com.test.templateMethod; publi ...

  8. [设计模式] 22 模板方法模式 template

    转http://www.jellythink.com/archives/407 在GOF的<设计模式:可复用面向对象软件的基础>一书中对模板方法模式是这样说的:定义一个操作中的算法骨架,而 ...

  9. java_设计模式_模板方法模式_Template Method Pattern(2016-08-11)

    定义: 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤.这里的算法的结构,可以理解为你根据需求设计出来的业务流程.特定的步骤就是指那些 ...

随机推荐

  1. 憋了很久,终于弄懂什么是IOC(控制反转)

    导航 共享充电宝 IOC思想 复杂的依赖关系 IOC定义 Spring中的IOC IOC与工厂模式 IOC容器的技术剖析 结语 参考   本节是摘自<Spring Boot 实战纪实>的第 ...

  2. 前端VUE基于gitlab的CI_CD

    目录 CI 1.Gitlab的CI 1.1 GitLab-Runner 1.2 .gitlab-ci.yml 1.3 配置.gitlab-ci.yml 1.3.1 Pipeline概念 1.3.2 S ...

  3. 3DGIS开发使用的开源项目

    gdal proj4 vcglib assimp libjpg libpng osg libtess2 cesiumjs glm

  4. xshell连接vmware系统完整版

    设置静态ip需要修改文件一共有两个要修改的文件vi /etc/resolv.confvi /etc/sysconfig/network-scripts/ifcfg-eno16777736 第一个文件 ...

  5. iOS自动化之WDA(WebDriverAgent)安装

    1.WDA介绍 WebDriverAgent 在 iOS 端实现了一个 WebDriver server ,借助这个 server 我们可以远程控制 iOS 设备.你可以启动.杀死应用,点击.滚动视图 ...

  6. c++-string类--insert函数

    string &insert(int p0, const char *s);--在p0位置插入字符串s string &insert(int p0, const char *s, in ...

  7. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  8. 宙斯盾 DDoS 防护系统“降本增效”的云原生实践

    作者 tomdu,腾讯云高级工程师,主要负责宙斯盾安全防护系统管控中心架构设计和后台开发工作. 导语 宙斯盾 DDoS 防护系统作为公司级网络安全产品,为各类业务提供专业可靠的 DDoS/CC 攻击防 ...

  9. 【数据结构与算法Python版学习笔记】树——相关术语、定义、实现方法

    概念 一种基本的"非线性"数据结构--树 根 枝 叶 广泛应用于计算机科学的多个领域 操作系统 图形学 数据库 计算机网络 特征 第一个属性是层次性,即树是按层级构建的,越笼统就越 ...

  10. 安装pytorch后import torch显示no module named 'torch'

    问题描述:在pycharm终端里通过pip指令安装pytorch,显示成功安装但是python程序和终端都无法使用pytorch,显示no module named 'torch'. 起因:电脑里有多 ...