Hourra ! La version française est enfin sortie ! Laissez-nous un message svp, si vous voulez nous faire part de vos commentaires ou signaler une erreur.
Patron de méthode

Patron de méthode en Go

Le Patron de méthode est un patron de conception comportemental qui permet de définir le squelette d’un algorithme dans la classe de base, et laisse les sous-classes redéfinir les étapes sans modifier la structure globale de l’algorithme.

Exemple conceptuel

Imaginons un exemple de fonctionnalité de mot de passe à usage unique. Nous disposons de plusieurs possibilités pour envoyer le mot de passe à un utilisateur (SMS, e-mail, etc.). Quelle que soit la façon de le communiquer, le processus complet pour le mot de passe à usage unique reste le même :

  1. Générer un nombre aléatoire avec n chiffres.
  2. Sauvegarder ce nombre dans le cache pour vérification ultérieure.
  3. Préparer le contenu.
  4. Envoyer la notification.
  5. Publier les indicateurs.

Tout nouveau type de mot de passe à usage unique ajouté dans le futur suivra probablement les mêmes étapes.

Nous nous retrouvons donc dans un scénario où les étapes d’un traitement particulier resteront les mêmes, seule leur implémentation pourra différer. C’est la situation idéale pour envisager d’utiliser le patron de méthode.

Tout d’abord, nous allons définir un modèle de base pour l’algorithme qui va être composé d’un nombre fixe de méthodes (notre patron de méthode). Ensuite nous implémenterons toutes les méthodes des étapes, sans toucher au patron de méthode.

otp.go: Patron de méthode

package main

type iOtp interface {
	genRandomOTP(int) string
	saveOTPCache(string)
	getMessage(string) string
	sendNotification(string) error
	publishMetric()
}

// type otp struct {
// }

// func (o *otp) genAndSendOTP(iOtp iOtp, otpLength int) error {
// 	otp := iOtp.genRandomOTP(otpLength)
// 	iOtp.saveOTPCache(otp)
// 	message := iOtp.getMessage(otp)
// 	err := iOtp.sendNotification(message)
// 	if err != nil {
// 		return err
// 	}
// 	iOtp.publishMetric()
// 	return nil
// }

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
}

sms.go: Implémentation concrète

package main

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: Implémentation concrète

package main

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: Code client

package main

import "fmt"

func main() {
	// otp := otp{}

	// smsOTP := &sms{
	// 	otp: otp,
	// }

	// smsOTP.genAndSendOTP(smsOTP, 4)

	// emailOTP := &email{
	// 	otp: otp,
	// }
	// emailOTP.genAndSendOTP(emailOTP, 4)
	// fmt.Scanln()
	smsOTP := &sms{}
	o := otp{
		iOtp: smsOTP,
	}
	o.genAndSendOTP(4)

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

}

output.txt: Résultat de l’exécution

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

Patron de méthode dans les autres langues

Patrons de conception : Patron de méthode en Java Patrons de conception : Patron de méthode en C# Patrons de conception : Patron de méthode en C++ Patrons de conception : Patron de méthode en PHP Patrons de conception : Patron de méthode en Python Patrons de conception : Patron de méthode en Ruby Patrons de conception : Patron de méthode en Swift Patrons de conception : Patron de méthode en TypeScript