模板方法模式是什么
模版方法模式是設計模式中的行為型的一種模式,它在基類中定義了一個演算法的框架,允許子類在不修改結構的情況下重寫演算法的特定步驟,
為什么要用模板方法模式
模板方法將整個演算法轉換為一系列獨立的步驟,以便子類能對其進行擴展,同時還可讓超類中所定義的結構保持完整,或者當多個類的演算法步驟一致,只是一些細微之處不同時,可用該模式,
模板方法模式怎么實作
讓我們來考慮一個一次性密碼功能(OTP)的例子,將OTP傳遞給用戶的方式多種多樣(短信、郵件等),但無論是短信還是郵件, 整個 OTP 流程都是相同的:
- 生成隨機的 n 位數字,
- 在快取中保存這組數字以便進行后續驗證,
- 準備內容,
- 發送通知,
- 發布,
我們定義了固定的模板方法,email和sms雖然實作了方式不同,但是都實作了相同的方法,后續如果有新的OTP型別也會實作相同的方法,
otp.go
package template_method
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
}
email.go
package template_method
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")
}
sms.go
package template_method
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")
}
example.go客戶端呼叫
package template_method
import "fmt"
func Example() {
smsOTP := &sms{}
o := otp{
iOtp: smsOTP,
}
o.genAndSendOTP(4)
fmt.Println("")
emailOTP := &email{}
o = otp{
iOtp: emailOTP,
}
o.genAndSendOTP(4)
}
優點:
- 它在父類中提取了公共的部分代碼,便于代碼復用,
- 它封裝了不變部分,擴展可變部分,它把認為是不變部分的演算法封裝到父類中實作,而把可變部分演算法由子類繼承實作,便于子類繼續擴展,
- 部分方法是由子類實作的,因此子類可以通過擴展方式增加相應的功能,符合開閉原則,
缺點:
- 對每個不同的實作都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象,間接地增加了系統實作和維護的復雜度,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/458083.html
標籤:其他
上一篇:約定編程與Sping AOP
