9.3.9 الگو Template Method

9.3.9 الگو Template Method

الگو Template Method…

9.3.9.1 مقدمه: #

الگوی Template Method یک الگوی طراحی behavioral است که به شما امکان می دهد یک الگو یا الگوریتم برای یک عملیات خاص تعریف کنید. بیایید الگوی Template Method را با یک مثال درک کنیم.

مثال یک مرز یک بار مصرف (One Time Password) یا OTP را در نظر بگیرید. انواع مختلفی از OTP وجود دارد که می تواند برای مثال اجرا شود. OTP می تواند SMS OTP یا EMAIL OTP باشد. اما صرف نظر از اینکه یک پیامک OTP یا EMAIL OTP باشد، کل مراحل فرآیند OTP یکسان است. مراحل مورد نظر به ترتیب زیر هستند.

  • یک عدد n رقمی تصادفی ایجاد کنید.
  • این شماره را برای تأیید بعدی در cache ذخیره کنید.
  • محتوا را آماده کنید
  • notification را ارسال کنید
  • metricsها را Publish کنید

حتی در آینده فرض کنید یک push notification OTP معرفی شده است، اما همچنان مراحل بالا را طی خواهد کرد.

در چنین سناریوهایی زمانی که مراحل یک عملیات خاص یکسان است اما مراحل عملیات می تواند به روشی متفاوت توسط مجریان مختلف اجرا شود. پس از آن بهترین گزینه برای انتخاب دیزاین پترن مناسب گزینه Template Method می شود. ما یک template یا الگوریتم را تعریف می کنیم که از methodهای fixed number تشکیل شده است. نوشتن برنامه برای حالت جدید باید operation override متدهای template را پیاده سازی کند.

حالا نمونه کد زیر را بررسی کنید.

iOtp نشان دهنده یک interface است که مجموعه متد هایی را که هر نوع otp باید پیاده سازی کند را تعریف می کند.

اس ام اس و ایمیل پیاده سازی رابط iOtp هستند

otp ساختاری است که متد template () genAndSendOTP را تعریف می کند. otp رابط iOtp را تعبیه می کند.

مهم: ترکیب رابط iOtp و ساختار otp قابلیت های Abstract Class را در زبان برنامه نویسی go فراهم می کند. برای اطلعات بیشتر در این مورد مرجع مراجعه کنید.

9.3.9.2 مثال: #

otp.go

 1package main
 2
 3type iOtp interface {
 4    genRandomOTP(int) string
 5    saveOTPCache(string)
 6    getMessage(string) string
 7    sendNotification(string) error
 8    publishMetric()
 9}
10
11type otp struct {
12    iOtp iOtp
13}
14
15func (o *otp) genAndSendOTP(otpLength int) error {
16    otp := o.iOtp.genRandomOTP(otpLength)
17    o.iOtp.saveOTPCache(otp)
18    message := o.iOtp.getMessage(otp)
19    err := o.iOtp.sendNotification(message)
20    if err != nil {
21        return err
22    }
23    o.iOtp.publishMetric()
24    return nil
25}

sms.go

 1package main
 2
 3import "fmt"
 4
 5type sms struct {
 6    otp
 7}
 8
 9func (s *sms) genRandomOTP(len int) string {
10    randomOTP := "1234"
11    fmt.Printf("SMS: generating random otp %s\n", randomOTP)
12    return randomOTP
13}
14
15func (s *sms) saveOTPCache(otp string) {
16    fmt.Printf("SMS: saving otp: %s to cache\n", otp)
17}
18
19func (s *sms) getMessage(otp string) string {
20    return "SMS OTP for login is " + otp
21}
22
23func (s *sms) sendNotification(message string) error {
24    fmt.Printf("SMS: sending sms: %s\n", message)
25    return nil
26}
27
28func (s *sms) publishMetric() {
29    fmt.Printf("SMS: publishing metrics\n")
30}

email.go

 1package main
 2
 3import "fmt"
 4
 5type email struct {
 6    otp
 7}
 8
 9func (s *email) genRandomOTP(len int) string {
10    randomOTP := "1234"
11    fmt.Printf("EMAIL: generating random otp %s\n", randomOTP)
12    return randomOTP
13}
14
15func (s *email) saveOTPCache(otp string) {
16    fmt.Printf("EMAIL: saving otp: %s to cache\n", otp)
17}
18
19func (s *email) getMessage(otp string) string {
20    return "EMAIL OTP for login is " + otp
21}
22
23func (s *email) sendNotification(message string) error {
24    fmt.Printf("EMAIL: sending email: %s\n", message)
25    return nil
26}
27
28func (s *email) publishMetric() {
29    fmt.Printf("EMAIL: publishing metrics\n")
30}

main.go

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

Output:

1SMS: generating random otp 1234
2SMS: saving otp: 1234 to cache
3SMS: sending sms: SMS OTP for login is 1234
4SMS: publishing metrics
5
6EMAIL: generating random otp 1234
7EMAIL: saving otp: 1234 to cache
8EMAIL: sending email: EMAIL OTP for login is 1234
9EMAIL: publishing metrics

9.3.9.3 مثال پیاده سازی شده به صورت یکجا: #

 1package main
 2
 3import "fmt"
 4
 5type iOtp interface {
 6    genRandomOTP(int) string
 7    saveOTPCache(string)
 8    getMessage(string) string
 9    sendNotification(string) error
10    publishMetric()
11}
12
13type otp struct {
14    iOtp iOtp
15}
16
17func (o *otp) genAndSendOTP(otpLength int) error {
18    otp := o.iOtp.genRandomOTP(otpLength)
19    o.iOtp.saveOTPCache(otp)
20    message := o.iOtp.getMessage(otp)
21    err := o.iOtp.sendNotification(message)
22    if err != nil {
23        return err
24    }
25    o.iOtp.publishMetric()
26    return nil
27}
28
29type sms struct {
30    otp
31}
32
33func (s *sms) genRandomOTP(len int) string {
34    randomOTP := "1234"
35    fmt.Printf("SMS: generating random otp %s\n", randomOTP)
36    return randomOTP
37}
38
39func (s *sms) saveOTPCache(otp string) {
40    fmt.Printf("SMS: saving otp: %s to cache\n", otp)
41}
42
43func (s *sms) getMessage(otp string) string {
44    return "SMS OTP for login is " + otp
45}
46
47func (s *sms) sendNotification(message string) error {
48    fmt.Printf("SMS: sending sms: %s\n", message)
49    return nil
50}
51
52func (s *sms) publishMetric() {
53    fmt.Printf("SMS: publishing metrics\n")
54}
55
56type email struct {
57    otp
58}
59
60func (s *email) genRandomOTP(len int) string {
61    randomOTP := "1234"
62    fmt.Printf("EMAIL: generating random otp %s\n", randomOTP)
63    return randomOTP
64}
65
66func (s *email) saveOTPCache(otp string) {
67    fmt.Printf("EMAIL: saving otp: %s to cache\n", otp)
68}
69
70func (s *email) getMessage(otp string) string {
71    return "EMAIL OTP for login is " + otp
72}
73
74func (s *email) sendNotification(message string) error {
75    fmt.Printf("EMAIL: sending email: %s\n", message)
76    return nil
77}
78
79func (s *email) publishMetric() {
80    fmt.Printf("EMAIL: publishing metrics\n")
81}
82
83func main() {
84    smsOTP := &sms{}
85    o := otp{
86        iOtp: smsOTP,
87    }
88    o.genAndSendOTP(4)
89    fmt.Println("")
90    emailOTP := &email{}
91    o = otp{
92        iOtp: emailOTP,
93    }
94    o.genAndSendOTP(4)
95}

Output:

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