GoLang design pattern 16 - template method pattern

Posted by Isomerizer on Thu, 27 Jan 2022 07:35:56 +0100

Template method design pattern is a behavioral design pattern. This pattern is commonly used to define a template or algorithm model for a specific operation.

Take OTP (One Time Password) as an example. There are two common one-time passwords: SMS password (SMS OTP) or email password (Email OTP). However, the processing steps of both SMS password and email password are the same, as follows:

  1. Generate a random string
  2. Save the string into the cache for subsequent validation
  3. Prepare notification content
  4. Send notification
  5. Record statistics

In the above steps, except that the specific method of "sending notice" in Item 4 is different, other steps remain unchanged. Even if there is a new one-time password sending method in the future, it can be predicted that the above steps will remain the same.

In such scenarios, that is, the steps of an operation are fixed, but there are differences in the specific execution methods. At this time, we can use the template method mode. In the template method mode, we usually define a template interface or algorithm model interface for this operation. The interface contains fixed methods, and then the specific implementation class rewrites the relevant interfaces and implements these operations.

The following is the implementation of the one-time password example:

otp.go

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 }

Briefly interpret this Code:

  • The iOtp interface is defined in the above code. The methods in this interface are the relevant steps required by OTP
  • The following sms and email are the implementation of iOtp interface
  • The template method genAndSendOTP() is defined in the structure otp

In addition, note that in the above code, the iOtp interface and structure otp are combined to provide an implementation similar to an abstract class, which can be used for reference when you need it.

sms.go

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import "fmt"   func main() {     smsOTP := &sms{}     o := otp{         iOtp: smsOTP,     }     o.genAndSendOTP(4)     fmt.Println("")     emailOTP := &email{}     o = otp{         iOtp: emailOTP,     }     o.genAndSendOTP(4) }

The output content is:

1 2 3 4 5 6 7 8 9 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

Code uploaded to GitHub: zhyea / go-patterns / template-method-pattern

END!!

 

Just learning notes will inevitably make mistakes. I hope you will give me some advice
 
Turn https://www.cnblogs.com/amunote/p/15586554.html

Topics: Go Design Pattern