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.
Défi
FacileConstruisons 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
Converteravec une méthodeConvert(content string) stringqui prend le contenu du document et retourne le résultat converti.Implémentez trois types de convertisseurs :
PDFConverter— sa méthodeConvertretournePDF: [content]HTMLConverter— sa méthodeConvertretourneHTML: <p>[content]</p>MarkdownConverter— sa méthodeConvertretourneMD: # [content]
Créez une fonction fabrique
NewConverter(format string) Converterqui retourne le convertisseur approprié en fonction de la chaîne de format (pdf,html, oumarkdown). Pour tout format non reconnu, retournez unPDFConverterpar 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 ProgrammingVotre sortie devrait être :
HTML: <p>Welcome to Go Programming</p>Et avec :
markdown
Chapter OneVotre sortie devrait être :
MD: # Chapter OneEt avec :
pdf
Annual Report 2024Votre sortie devrait être :
PDF: Annual Report 2024Et avec :
docx
Meeting NotesVotre sortie devrait être :
PDF: Meeting NotesRemarquez 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)
}
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
1Fondamentaux de la POO en Go
Fichiers externesEspace de travail et Modules GoPackages et ImportsNoms exportés vs non exportésIntroduction à la POO en GoLes Structs comme ClassesDéfinir des méthodes sur les StructsReceveurs par pointeur vs par valeurInitialisation de StructsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL'interface comme contratInterface vide (any)Assertion de typeType SwitchComposition d'interfacesInterfaces Stringer & ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter & SetterMasquage d'informations en GoRécapitulatif - Dossiers étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesContournement pour les méthodes génériquesRécapitulatif - Collections génériques13Patrons de conception, Partie 1
Introduction aux Design PatternsPatron SingletonPatron FactoryPatron Abstract FactoryPatron ObserverPatron Strategy2Exploration approfondie des Types et Structs
Types de base et compositesDéfinitions de types personnalisésTags de StructStructs anonymesStructs imbriquéesValeurs par défaut et Zero ValuesRécapitulatif - Carnet de contacts5Composition plutôt qu'héritage
Pourquoi Go n'a pas d'héritageLes bases de l'imbrication de structsPromotion de méthodesImbriquer plusieurs structsImbrication vs AgrégationMasquage de méthodes imbriquéesRécapitulatif - Hiérarchie des employés8Gestion des erreurs & POO
L'interface errorTypes d'erreurs personnalisésError Wrapping (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - File Parser11Bibliothèque standard et POO
io.Reader & io.WriterL'interface sort.InterfaceL'interface fmt.Stringerencoding/json avec les StructsL'interface http.HandlerRécapitulatif - Modèles d'API REST14Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositeMiddleware en tant que Décorateur3Pointeurs et Mémoire
Bases des pointeurs en GoPointeurs vers des structsPassage par valeur vs référenceLa fonction new()Garbage Collection en GoRécapitulatif - Constructeur de liste chaînée6Le polymorphisme en Go
Le polymorphisme via les interfacesLe Duck Typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif - Processeur de paiement9Concurrence et POO
Bases des GoroutinesChannels et CommunicationChannels avec buffer vs sans bufferL'instruction Selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures Thread-SafeRécapitulatif - Worker Pool