SOLDES de printemps
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.

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
}

// 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
// 	}
// 	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
	}
	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
}

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
}

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

EMAIL: generating random otp 1234
EMAIL: saving otp: 1234 to cache
EMAIL: sending email: EMAIL OTP for login is 1234

Patron de méthode dans les autres langues

Patron de méthode en C# Patron de méthode en C++ Patron de méthode en Java Patron de méthode en PHP Patron de méthode en Python Patron de méthode en Ruby Patron de méthode en Rust Patron de méthode en Swift Patron de méthode en TypeScript