Menu
Coddy logo textTech

Modèle Décorateur

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 93 sur 107.

Le pattern Decorator vous permet d’ajouter dynamiquement un nouveau comportement aux objets en les enveloppant dans d’autres objets. Alors que Adapter modifie une interface pour l’adapter à une autre, Decorator conserve la même interface, mais améliore les fonctionnalités en superposant des enveloppes autour de l’objet d’origine.

En Go, nous implémentons cela en faisant en sorte que le type de base et les décorateurs implémentent la même interface :

type Notifier interface {
    Send(message string) string
}

type BasicNotifier struct{}

func (b BasicNotifier) Send(message string) string {
    return "Sending: " + message
}

Les décorateurs enveloppent un autre Notifier et ajoutent un comportement avant ou après lui avoir délégué l’exécution :

type TimestampDecorator struct {
    wrapped Notifier
}

func (t TimestampDecorator) Send(message string) string {
    timestamped := "[2024-01-15] " + message
    return t.wrapped.Send(timestamped)
}

type UppercaseDecorator struct {
    wrapped Notifier
}

func (u UppercaseDecorator) Send(message string) string {
    return strings.ToUpper(u.wrapped.Send(message))
}

La puissance du modèle Decorator réside dans l’empilement de plusieurs enveloppes pour combiner les comportements :

notifier := BasicNotifier{}
withTimestamp := TimestampDecorator{wrapped: notifier}
withBoth := UppercaseDecorator{wrapped: withTimestamp}

fmt.Println(notifier.Send("Hello"))
// Envoi : Hello

fmt.Println(withBoth.Send("Hello"))
// ENVOI : [2024-01-15] HELLO

Le décorateur est idéal lorsque vous devez ajouter des responsabilités aux objets sans modifier leur code, en particulier lorsque différentes combinaisons de fonctionnalités sont nécessaires. Il est couramment utilisé pour les couches de journalisation, de mise en cache, d’authentification et de compression.

challenge icon

Défi

Facile

Construisons un système de commande pour un café en utilisant le pattern Decorator ! Tu vas créer une boisson à base de café et des décorateurs qui ajoutent des extras comme du lait, du sucre et de la crème fouettée. Chaque décorateur enveloppe le précédent, en construisant à la fois la description et le prix : un parfait exemple concret de la façon dont les décorateurs ajoutent des fonctionnalités par couches.

Tu organiseras ton code sur trois fichiers :

  • beverage.go : définis ton interface principale et ton type de café de base.

    Crée une interface Beverage avec deux méthodes :

    • Description() string : renvoie ce qu'est la boisson
    • Cost() float64 : renvoie le prix

    Implémente une structure Coffee comme boisson de base. Sa description doit être Coffee et son coût doit être 2.00.

  • decorators.go : crée tes types de décorateurs qui ajoutent des extras à n'importe quelle boisson.

    Chaque décorateur enveloppe un Beverage et implémente la même interface. Construis trois décorateurs :

    • MilkDecorator : ajoute , Milk à la description et 0.50 au coût
    • SugarDecorator : ajoute , Sugar à la description et 0.25 au coût
    • WhipDecorator : ajoute , Whip à la description et 0.75 au coût

    Chaque décorateur doit appeler les méthodes de la boisson enveloppée et enrichir le résultat.

  • main.go : construis des boissons personnalisées en empilant les décorateurs.

    Lis un nombre d'extras à ajouter. Ensuite, pour chaque extra, lis son type (milk, sugar ou whip) et enveloppe ta boisson actuelle avec le décorateur approprié.

    Après avoir appliqué tous les extras, affiche la description et le coût de la boisson finale sur des lignes séparées. Formate le coût sous la forme $X.XX avec exactement deux décimales.

Les entrées suivantes seront fournies :

  • Ligne 1 : nombre d'extras à ajouter
  • Lignes suivantes : un type d'extra par ligne (milk, sugar ou whip)

Par exemple, avec :

2
milk
sugar

Ta sortie doit être :

Coffee, Milk, Sugar
$2.75

Et avec :

3
whip
milk
milk

Ta sortie doit être :

Coffee, Whip, Milk, Milk
$3.75

Et avec :

0

Ta sortie doit être :

Coffee
$2.00

Remarque comment chaque décorateur enveloppe la boisson précédente, en construisant à la fois la description et le coût. Tu peux ajouter le même extra plusieurs fois (comme une double dose de lait), et l'ordre des décorateurs détermine l'ordre dans la description. Le café de base ne sait rien des extras : chaque décorateur enrichit simplement ce qu'il enveloppe !

Essayez vous-même

package main

import (
	"fmt"
)

func main() {
	// Lire le nombre d'extras
	var count int
	fmt.Scanln(&count)

	// Commencer avec un café de base
	var drink Beverage = &Coffee{}

	// Lire chaque extra et envelopper drink avec le décorateur approprié
	for i := 0; i < count; i++ {
		var extra string
		fmt.Scanln(&extra)

		// TODO: En fonction du type d'extra, envelopper drink avec le décorateur approprié
		// Utiliser MilkDecorator pour "milk"
		// Utiliser SugarDecorator pour "sugar"
		// Utiliser WhipDecorator pour "whip"
	}

	// TODO: Afficher la description finale et le coût
	// Formater le coût comme $X.XX avec exactement deux décimales
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne