Menu
Coddy logo textTech

Modèle Composite

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

Le patron Composite vous permet de traiter uniformément les objets individuels et les groupes d’objets. Alors que State modifie le comportement en fonction de l’état interne, Composite construit des structures arborescentes dans lesquelles les feuilles et les conteneurs partagent la même interface.

Ce modèle est parfait pour les structures hiérarchiques telles que les systèmes de fichiers, les organigrammes ou les composants d’interface utilisateur. En Go, nous définissons une interface commune que les éléments individuels et les conteneurs implémentent :

type Component interface {
    GetSize() int
}

type File struct {
    Name string
    Size int
}

func (f File) GetSize() int {
    return f.Size
}

Le composite (conteneur) contient des enfants et implémente la même interface en agrégeant leurs résultats :

type Folder struct {
    Name     string
    Children []Component
}

func (f *Folder) Add(c Component) {
    f.Children = append(f.Children, c)
}

func (f Folder) GetSize() int {
    total := 0
    for _, child := range f.Children {
        total += child.GetSize()
    }
    return total
}

Vous pouvez maintenant imbriquer des dossiers dans des dossiers, et l’appel de GetSize() fonctionne de manière identique, qu’il s’agisse d’un seul fichier ou d’une arborescence de répertoires entière :

docs := &Folder{Name: "docs"}
docs.Add(File{Name: "readme.txt", Size: 100})
docs.Add(File{Name: "notes.txt", Size: 50})

root := &Folder{Name: "root"}
root.Add(docs)
root.Add(File{Name: "config.json", Size: 25})

fmt.Println(root.GetSize())  // 175

Le modèle Composite est idéal lorsque vous devez représenter des hiérarchies partie-tout et que vous voulez que les clients traitent les objets individuels et les compositions de manière identique.

challenge icon

Défi

Facile

Construisons un système d’organigramme en utilisant le pattern Composite ! Vous allez créer une structure dans laquelle les employés individuels et les départements (qui contiennent des employés ou d’autres départements) peuvent être traités uniformément, ce qui est idéal pour calculer les salaires totaux de n’importe quelle partie de l’organisation.

Vous allez organiser votre code dans trois fichiers :

  • component.go : définissez l’interface commune que les individus et les groupes implémenteront.

    Créez une interface OrgComponent avec deux méthodes :

    • GetSalary() int : renvoie le salaire total de ce composant
    • GetName() string : renvoie le nom de l’employé ou du département
  • organization.go : implémentez les types feuille (employé individuel) et composite (département).

    Créez une structure Employee avec les champs Name (string) et Salary (int). Son GetSalary() renvoie son propre salaire, et GetName() renvoie son nom.

    Créez une structure Department avec un champ Name (string) et une tranche Members contenant des éléments OrgComponent. Ajoutez une méthode Add(c OrgComponent) pour ajouter des membres. Son GetSalary() doit renvoyer la somme des salaires de tous les membres, et GetName() renvoie le nom du département.

  • main.go : construisez une structure organisationnelle et calculez les salaires.

    Lisez le nombre d’employés. Pour chaque employé, lisez son nom et son salaire en créant des instances de Employee. Lisez ensuite le nombre de départements. Pour chaque département, lisez son nom et le nombre d’indices de membres, puis ces indices (en base 0, faisant référence aux employés ou départements précédemment créés, dans leur ordre de création).

    Après avoir construit la structure, lisez un indice final et affichez le nom et le salaire total de ce composant au format : [name]: [salary]

Les entrées suivantes seront fournies :

  • Le nombre d’employés, puis le nom et le salaire de chaque employé sur des lignes séparées
  • Le nombre de départements, puis le nom de chaque département, le nombre de membres et les indices des membres
  • L’indice final à interroger

Par exemple, étant donné :

3
Alice
50000
Bob
60000
Carol
55000
1
Engineering
3
0
1
2
3

Votre sortie doit être :

Engineering: 165000

Et étant donné :

4
Alice
50000
Bob
60000
Carol
55000
Dave
70000
2
Dev
2
0
1
QA
2
2
3
4

Votre sortie doit être :

QA: 125000

Et étant donné :

2
Alice
50000
Bob
60000
0
1

Votre sortie doit être :

Bob: 60000

Remarquez que GetSalary() fonctionne de manière identique, que vous l’appeliez sur un seul employé ou sur un département entier : le pattern Composite vous permet de traiter uniformément les individus et les groupes au moyen de la même interface !

Essayez vous-même

package main

import "fmt"

func main() {
	// Lire le nombre d'employés
	var numEmployees int
	fmt.Scanln(&numEmployees)

	// Stocker tous les composants (employés et départements) dans l'ordre de création
	var components []OrgComponent

	// TODO: Lire le nom et le salaire de chaque employé
	// Créer des instances Employee et les ajouter au slice components
	for i := 0; i < numEmployees; i++ {
		var name string
		var salary int
		fmt.Scanln(&name)
		fmt.Scanln(&salary)
		// TODO: Créer l'employé et l'ajouter à components
	}

	// Lire le nombre de départements
	var numDepartments int
	fmt.Scanln(&numDepartments)

	// TODO: Lire le nom de chaque département, le nombre de membres et les indices des membres
	// Créer des instances Department, ajouter les membres par index, et ajouter à components
	for i := 0; i < numDepartments; i++ {
		var deptName string
		var memberCount int
		fmt.Scanln(&deptName)
		fmt.Scanln(&memberCount)
		// TODO: Créer le département, lire les indices des membres, ajouter les membres, ajouter à components
	}

	// Lire l'index final à interroger
	var queryIndex int
	fmt.Scanln(&queryIndex)

	// TODO: Afficher le nom du composant et le salaire total au format : [name]: [salary]
	// Exemple: fmt.Printf("%s: %d\n", name, salary)
}
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