Menu
Coddy logo textTech

Patron Factory

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy — leçon 87 sur 107.

Le patron Factory délègue la création d'objets à une fonction ou une méthode distincte, vous permettant de créer des instances sans exposer la logique de création. Contrairement au Singleton qui contrôle le nombre d'instances, Factory se concentre sur la création flexible d'objets basée sur des paramètres d'entrée.

En Go, une fabrique (factory) est généralement une fonction qui renvoie un type d'interface, vous permettant de créer différents types concrets via une API unifiée :

type Notifier interface {
    Send(message string) string
}

type EmailNotifier struct{}
type SMSNotifier struct{}

func (e EmailNotifier) Send(message string) string {
    return "Email: " + message
}

func (s SMSNotifier) Send(message string) string {
    return "SMS: " + message
}

func NewNotifier(notifierType string) Notifier {
    switch notifierType {
    case "email":
        return EmailNotifier{}
    case "sms":
        return SMSNotifier{}
    default:
        return EmailNotifier{}
    }
}

La fonction factory NewNotifier encapsule la décision du type concret à créer. Le code client travaille uniquement avec l'interface Notifier, tout en restant ignorant de l'implémentation spécifique :

notifier := NewNotifier("sms")
result := notifier.Send("Hello!")  // "SMS: Hello!"

Ce patron s'illustre particulièrement lorsque vous devez créer des objets en fonction de conditions d'exécution, que vous souhaitez centraliser une logique d'initialisation complexe, ou que vous avez besoin d'ajouter facilement de nouveaux types sans modifier le code client. Il suffit d'ajouter une nouvelle struct implémentant l'interface et de mettre à jour la factory function.

challenge icon

Défi

Facile

Construisons un système de conversion de documents en utilisant le pattern Factory ! Vous allez créer une fabrique qui produit différents convertisseurs de documents en fonction du format cible, permettant au code client de travailler avec n'importe quel convertisseur via une interface unifiée.

Vous organiserez votre code sur deux fichiers :

  • converter.go : Définissez votre interface de convertisseur et les implémentations concrètes.

    Créez une interface Converter avec une méthode Convert(content string) string qui prend le contenu du document et retourne le résultat converti.

    Implémentez trois types de convertisseurs :

    • PDFConverter — sa méthode Convert retourne PDF: [content]
    • HTMLConverter — sa méthode Convert retourne HTML: <p>[content]</p>
    • MarkdownConverter — sa méthode Convert retourne MD: # [content]

    Créez une fonction fabrique NewConverter(format string) Converter qui retourne le convertisseur approprié en fonction de la chaîne de format (pdf, html, ou markdown). Pour tout format non reconnu, retournez un PDFConverter par défaut.

  • main.go : Utilisez votre fabrique pour créer des convertisseurs et traiter des documents.

    Lisez un type de format et le contenu du document. Utilisez la fabrique pour créer le convertisseur approprié, puis convertissez le contenu et affichez le résultat.

Les entrées suivantes seront fournies :

  • Ligne 1 : Type de format (pdf, html, markdown, ou autre chose)
  • Ligne 2 : Contenu du document à convertir

Par exemple, avec :

html
Welcome to Go Programming

Votre sortie devrait être :

HTML: <p>Welcome to Go Programming</p>

Et avec :

markdown
Chapter One

Votre sortie devrait être :

MD: # Chapter One

Et avec :

pdf
Annual Report 2024

Votre sortie devrait être :

PDF: Annual Report 2024

Et avec :

docx
Meeting Notes

Votre sortie devrait être :

PDF: Meeting Notes

Remarquez comment le code principal n'a pas besoin de connaître les types de convertisseurs spécifiques — il demande simplement un convertisseur à la fabrique et utilise l'interface. Cela facilite l'ajout de nouveaux formats plus tard sans modifier le code client !

Aide-mémoire

Le pattern Factory (ou fabrique) délègue la création d'objets à une fonction distincte, vous permettant de créer des instances sans exposer la logique de création. Il se concentre sur la création flexible d'objets basée sur des paramètres d'entrée.

Une fonction factory retourne un type interface, permettant la création de différents types concrets via une API unifiée :

type Notifier interface {
    Send(message string) string
}

type EmailNotifier struct{}
type SMSNotifier struct{}

func (e EmailNotifier) Send(message string) string {
    return "Email: " + message
}

func (s SMSNotifier) Send(message string) string {
    return "SMS: " + message
}

func NewNotifier(notifierType string) Notifier {
    switch notifierType {
    case "email":
        return EmailNotifier{}
    case "sms":
        return SMSNotifier{}
    default:
        return EmailNotifier{}
    }
}

Le code client travaille uniquement avec l'interface, restant ignorant des implémentations spécifiques :

notifier := NewNotifier("sms")
result := notifier.Send("Hello!")  // "SMS: Hello!"

Ce pattern est utile lorsque vous devez créer des objets basés sur des conditions d'exécution, que vous souhaitez centraliser une logique d'initialisation complexe, ou que vous devez ajouter de nouveaux types sans modifier le code client.

Essayez vous-même

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Lire le type de format
	scanner.Scan()
	format := scanner.Text()
	
	// Lire le contenu du document
	scanner.Scan()
	content := scanner.Text()
	
	// TODO : Utiliser la fabrique pour créer le convertisseur approprié
	// TODO : Convertir le contenu et afficher le résultat
	
	fmt.Println(result)
}
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