1. Qu'est-ce que le motif de conception composite
Le motif composite est un motif de conception structurel d'objet couramment utilisé. Il combine des objets dans une structure arborescente pour représenter une relation hiérarchique "partie-tout", permettant aux clients de manipuler des objets individuels et des compositions d'objets de manière cohérente.
2. Caractéristiques et avantages du motif composite
Les principaux avantages du motif composite sont les suivants :
- Il peut clairement définir les objets hiérarchiques complexes, représentant toute ou partie de la hiérarchie des objets, ce qui rend plus facile l'ajout de nouveaux composants.
- Il fournit une interface unifiée, rendant l'accès aux parties composites et aux objets individuels cohérent, permettant aux clients d'utiliser uniformément les objets simples et les objets composites.
3. Scénarios d'application du motif composite
- Lorsque vous souhaitez représenter la hiérarchie "partie-tout" des objets.
- Lorsque vous souhaitez que les clients ignorent les différences entre les objets composites et les objets individuels, et utilisent uniformément tous les objets dans la structure composite.
4. Implémentation du motif composite en Golang
Supposons que nous concevons une application de commerce électronique, le catalogue de produits est un bon exemple du motif composite. Une catégorie peut contenir d'autres catégories, ainsi que des produits (comme la catégorie électronique contient des téléphones, des ordinateurs, et les téléphones contiennent des iPhones, des téléphones Samsung, etc.).
4.1 Diagramme de classe UML
4.2 Introduction de l'exemple
Dans cet exemple, nous avons Component
(en utilisant évidemment la fonctionnalité d'interface de l'orientation objet) en tant que classe de base abstraite, et Composite
et Leaf
implémentent tous deux cette interface, représentant respectivement des objets conteneurs et des objets de base.
4.3 Étape 1 d'implémentation : Définir la classe de composant abstrait
4.3.1 Définir l'interface de la classe de composant abstrait
// Component: Interface de composant de base, définit la similitude des groupes et des individus
type Component interface {
Search(string)
}
4.3.2 Implémenter les méthodes de base de la classe de composant abstrait
Cette étape est spécifiquement implémentée dans la classe de composant conteneur et la classe de composant feuille.
4.4 Étape 2 d'implémentation : Définir la classe de composant feuille
Cette classe concrète représente la catégorie ou l'objet de base dans la hiérarchie, et elle n'a pas de prochaine couche d'objets.
4.4.1 Héritage de la classe de composant abstrait
En Go, l'héritage d'interface est implémenté par la manière dont les méthodes sont implémentées à travers Struct.
4.4.2 Implémenter les méthodes spécifiques à la classe de composant feuille
// Product: Représente un nœud feuille, c'est-à-dire un produit, et ne peut pas avoir de nœuds enfants
type Product struct {
Name string
}
// Search: Rechercher des produits
func (p *Product) Search(keyword string) {
if strings.Contains(p.Name, keyword) {
fmt.Printf("Produit : '%s' contient le mot-clé : '%s'\n", p.Name, keyword)
}
}
4.5 Étape 3 d'implémentation : Définir la classe de composant conteneur
Cette classe est utilisée pour stocker et gérer les objets enfants, comprenant généralement des méthodes pour gérer et organiser les objets enfants, telles que add(Component)
, remove(Component)
, etc.
4.5.1 Héritage de la classe de composant abstrait
Cela est également implémenté en utilisant Struct pour implémenter les méthodes d'interface en Go.
4.5.2 Implémentation de méthodes spécifiques à la classe de composant conteneur
// Category: Représente un nœud conteneur, c'est-à-dire une catégorie de produits, qui peut avoir des nœuds enfants
type Category struct {
Name string
Children []Component
}
// Add: Ajouter un nœud enfant
func (c *Category) Add(child Component) {
c.Children = append(c.Children, child)
}
// Remove: Supprimer un nœud enfant
func (c *Category) Remove(child Component) {
// Implémentation spécifique omise
}
// Search: Rechercher des produits
func (c *Category) Search(keyword string) {
fmt.Printf("Catégorie: %s\n", c.Name)
for _, composite := range c.Children {
composite.Search(keyword)
}
}
4.6 Étape d'implémentation 4: Exemple de code client
Instanciez une structure, assemblez-la en une structure arborescente, puis appelez l'opération d'accès de la structure arborescente.
func main() {
root := &Category{Name: "Racine"}
electronics := &Category{Name: "Électronique"}
phone := &Product{Name: "Téléphone"}
tv := &Product{Name: "Télévision"}
root.Add(electronics)
electronics.Add(phone)
electronics.Add(tv)
root.Search("téléphone") // Cela recherchera dans tous les enfants
}