1. design-patterns/

golang 模板方法模式讲解和代码示例

·323 字·2 分钟· loading
设计模式 设计模式 golang
demo007x
作者
demo007x
设计模式 - This article is part of a series.
Part : This Article

Go 模板方法模式讲解和代码示例
#

模版方法是一种行为设计模式, 它在基类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

概念示例
#

让我们来考虑一个一次性密码功能 (OTP) 的例子。 将 OTP 传递给用户的方式多种多样 (短信、 邮件等)。 但无论是短信还是邮件, 整个 OTP 流程都是相同的:

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

后续引入的任何新 OTP 类型都很有可能需要进行相同的上述步骤。

因此, 我们会有这样的一个场景, 其中某个特定操作的步骤是相同的, 但实现方式却可能有所不同。 这正是适合考虑使用模板方法模式的情况。

首先, 我们定义一个由固定数量的方法组成的基础模板算法。 这就是我们的模板方法。 然后我们将实现每一个步骤方法, 但不会改变模板方法。

otp.go: 模板方法
#

package main

type IOtp interface {
	genRandomOPT(int) string
	saveOPTCache(string)
	getMessage(string) string
	sendNotification(string) error
}

type Otp struct {
	iOtp IOtp
}

func (o *Otp) genAndSendOPT(optLength int) error {
	opt := o.iOtp.genRandomOPT(optLength)
	o.iOtp.saveOPTCache(opt)
	message := o.iOtp.getMessage(opt)
	if err := o.iOtp.sendNotification(message); err != nil {
		return err
	}
	return nil
}

sms.go: 具体实施
#

package main

import (
	"fmt"
)

type Sms struct {
	Otp
}

func (s *Sms) genRandomOPT(len int) string {
	randomOTP := "1234"
	fmt.Printf("SMS: generating random otp %s \n", randomOTP)
	return randomOTP
}

func (s *Sms) saveOPTCache(otp string) {
	fmt.Printf("SMS: saving otp %s", 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) genRandomOPT(len int) string {
	randomOTP := "2345"
	fmt.Printf("Email: generating random otp %s \n", randomOTP)
	return randomOTP
}

func (s *Email) saveOPTCache(otp string) {
	fmt.Printf("Email: saving otp %s to cache", 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.genAndSendOPT(4)

	fmt.Println("")
	emailOtp := &Email{}
	o = Otp{
		iOtp: emailOtp,
	}
	o.genAndSendOPT(4)
}

output.txt: 执行结果
#

SMS: generating random otp 1234 
SMS: saving otp 1234SMS: sending sms: SMS OTP for login is 1234

Email: generating random otp 2345 
Email: saving otp 2345 to cacheEmail: sending email Email otp for login is 2345 
设计模式 - This article is part of a series.
Part : This Article

Related

golang 策略模式讲解和代码示例
设计模式 设计模式 golang
策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策略对象。
golang 状态模式讲解和代码示例
设计模式 设计模式 golang
状态是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为。该模式将与状态相关的行为抽取到独立的状态类中, 让原对象将工作委派给这些类的实例, 而不是自行进行处理。
golang 单例模式讲解和代码示例
设计模式 设计模式 golang
单例是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。单例拥有与全局变量相同的优缺点。 尽管它们非常有用, 但却会破坏代码的模块化特性。在某些其他上下文中, 你不能使用依赖于单例的类。 你也将必须使用单例类。 绝大多数情况下, 该限制会在创建单元测试时出现。