Pattern Abstract Factory
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 88 sur 107.
Le patron Fabrique abstraite étend le patron Fabrique en créant des familles d’objets associés sans spécifier leurs types concrets. Au lieu d’une seule fonction fabrique, vous définissez une interface de fabrique que plusieurs fabriques concrètes implémentent, chacune produisant un ensemble cohérent d’objets associés.
Imaginez une boîte à outils d’interface utilisateur qui doit créer des boutons et des cases à cocher. Différents systèmes d’exploitation nécessitent des implémentations différentes, mais les composants doivent fonctionner ensemble de manière cohérente :
type Button interface {
Render() string
}
type Checkbox interface {
Check() string
}
// Interface de fabrique abstraite
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}Chaque fabrique concrète produit une famille de composants associés :
// Famille Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }
type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }
type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }
// Famille Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }
type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }
type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }Le code client fonctionne avec l’interface de fabrique, tout en restant indépendant des implémentations concrètes :
func BuildUI(factory GUIFactory) {
button := factory.CreateButton()
checkbox := factory.CreateCheckbox()
fmt.Println(button.Render(), checkbox.Check())
}Utilisez Abstract Factory lorsque votre système doit fonctionner avec plusieurs familles de produits associés et que vous souhaitez garantir que les composants de la même famille sont utilisés ensemble. Ce modèle est plus complexe qu’une Factory simple ; utilisez-le donc uniquement lorsque vous devez réellement gérer des familles de produits.
Défi
FacileConstruisons un système de magasin de meubles en utilisant le modèle Abstract Factory ! Vous créerez des fabriques qui produisent des familles d’articles de mobilier associés : chaque fabrique produit un style cohérent (Modern ou Vintage), garantissant que les chaises et les tables provenant de la même fabrique s’accordent esthétiquement.
Vous organiserez votre code dans trois fichiers :
furniture.go: définissez vos interfaces de produits et vos types de meubles concrets.Créez deux interfaces de produits :
Chairavec une méthodeSitOn() stringTableavec une méthodePlaceItems() string
Implémentez deux familles de meubles :
- Famille Modern :
ModernChairrenvoieSitting on a sleek modern chairetModernTablerenvoiePlacing items on a glass modern table - Famille Vintage :
VintageChairrenvoieSitting on an ornate vintage chairetVintageTablerenvoiePlacing items on a wooden vintage table
factory.go: définissez votre interface de fabrique abstraite et vos fabriques concrètes.Créez une interface
FurnitureFactoryavec deux méthodes :CreateChair() ChairCreateTable() Table
Implémentez deux fabriques concrètes :
ModernFactoryqui produitModernChairetModernTableVintageFactoryqui produitVintageChairetVintageTable
Créez également une fonction
GetFactory(style string) FurnitureFactoryqui renvoie la fabrique appropriée en fonction du style (modernouvintage). UtilisezModernFactorypar défaut pour les styles non reconnus.main.go: utilisez vos fabriques pour meubler des pièces.Créez une fonction
FurnishRoom(factory FurnitureFactory) stringqui utilise la fabrique pour créer une chaise et une table, puis renvoie une chaîne formatée affichant les deux actions sur des lignes séparées.Lisez une entrée de style, obtenez la fabrique appropriée, meublez une pièce et affichez le résultat.
Les entrées suivantes seront fournies :
- Ligne 1 : style du mobilier (
modern,vintageou autre chose)
Par exemple, pour :
modernVotre sortie doit être :
Sitting on a sleek modern chair
Placing items on a glass modern tableEt pour :
vintageVotre sortie doit être :
Sitting on an ornate vintage chair
Placing items on a wooden vintage tableEt pour :
rusticVotre sortie doit être :
Sitting on a sleek modern chair
Placing items on a glass modern tableRemarquez comment la fonction FurnishRoom fonctionne avec n’importe quelle fabrique grâce à l’interface. Elle ne sait pas si elle crée des meubles modernes ou vintage. Cela garantit que tous les meubles d’une pièce proviennent de la même famille, ce qui préserve un style cohérent !
Essayez vous-même
package main
import "fmt"
// FurnishRoom utilise une factory pour créer des meubles et renvoie le résultat
// TODO: Implémenter cette fonction
// - Utiliser la factory pour créer une chaise et une table
// - Renvoyer une chaîne avec le résultat de SitOn() sur la première ligne et le résultat de PlaceItems() sur la deuxième ligne
func FurnishRoom(factory FurnitureFactory) string {
// TODO: Créer une chaise et une table en utilisant la factory
// TODO: Renvoyer une chaîne formatée avec les deux actions sur des lignes séparées
return ""
}
func main() {
var style string
fmt.Scanln(&style)
// TODO: Obtenir la factory appropriée selon le style
// TODO: Meubler une pièce en utilisant la factory
// TODO: Afficher le résultat
}
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 et non exportésIntroduction à la POO en GoStructs comme classesDéfinir des méthodes sur des structsRécepteurs pointeurs ou par valeurInitialisation des structsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL’interface comme contratInterface vide (any)Assertion de typeCommutation de typeComposition d’interfacesInterfaces Stringer et ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter et SetterDissimulation de l’information en GoRécapitulatif – Fiches d’étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesSolution de contournement pour les méthodes génériquesRécapitulatif - Collection générique13Design Patterns – Partie 1
Introduction aux Design PatternsPattern SingletonPattern FactoryPattern Abstract FactoryPattern ObserverPattern Strategy2Plongée approfondie dans les types et les structs
Types de base et compositesDéfinitions de types personnalisésTags de structStructs anonymesStructs imbriquésValeurs zéro et valeurs par défautRécapitulatif - Carnet de contacts5La composition plutôt que l’héritage
Pourquoi Go n’a pas d’héritageBases de l’inclusion de structsPromotion des méthodesInclure plusieurs structsInclusion ou agrégationMasquage des méthodes inclusesRécapitulatif : hiérarchie des employés8Gestion des erreurs et POO
L’interface errorTypes d’erreurs personnalisésEnrobage des erreurs (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - Analyseur de fichiers11Bibliothèque standard et POO
io.Reader et io.Writersort.InterfaceInterface fmt.Stringerencoding/json avec des structsInterface http.HandlerRécapitulatif - Modèles d’API REST14Modèles de conception – Partie 2
Modèle CommandeModèle AdaptateurModèle DécorateurModèle Méthode modèleModèle ÉtatModèle CompositeMiddleware comme décorateur3Pointeurs et mémoire
Notions de base des pointeurs en GoPointeurs vers des structuresPassage par valeur ou par référenceLa fonction new()Garbage collection en GoRécapitulatif - Constructeur de listes chaînées6Polymorphisme en Go
Polymorphisme via les interfacesDuck typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif – Processeur de paiements9Concurrence et POO
Bases des GoroutinesCanaux et communicationCanaux tamponnés ou non tamponnésInstruction selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures thread-safeRécapitulatif - Pool de workersEntraînez-vous par vous-même : Compilateur Go en ligne