1. Was ist das Composite Pattern
Das Composite Pattern ist ein weit verbreitetes strukturelles Entwurfsmuster. Es kombiniert Objekte zu einer Baumstruktur, um eine hierarchische "Teil-Ganzes"-Beziehung darzustellen, wodurch es den Clients ermöglicht wird, individuelle Objekte und Objektkompositionen einheitlich zu handhaben.
2. Merkmale und Vorteile des Composite Pattern
Die Hauptvorteile des Composite Patterns sind:
- Es kann hierarchisch komplexe Objekte eindeutig definieren, die die gesamte oder einen Teil der Objekthierarchie darstellen und somit das Hinzufügen neuer Komponenten erleichtern.
- Es bietet eine einheitliche Schnittstelle, die den Zugriff auf zusammengesetzte Teile und individuelle Objekte konsistent macht und es den Clients ermöglicht, einheitlich einzelne Objekte und zusammengesetzte Objekte zu verwenden.
3. Anwendungsszenarien des Composite Patterns
- Wenn Sie die Teil-Ganzes-Hierarchie von Objekten darstellen möchten.
- Wenn Sie möchten, dass die Clients die Unterschiede zwischen zusammengesetzten Objekten und einzelnen Objekten ignorieren und alle Objekte in der zusammengesetzten Struktur einheitlich verwenden können.
4. Implementierung des Composite Patterns in Golang
Angenommen, wir entwerfen eine E-Commerce-Anwendung, der Produktkatalog ist ein gutes Beispiel für das Composite Pattern. Eine Kategorie kann andere Kategorien und auch Produkte enthalten (z. B. die Elektronik-Kategorie enthält Telefone, Computer und Telefone enthalten iPhones, Samsung-Telefone, usw.).
4.1 UML-Klassendiagramm
4.2 Beispiel Einführung
In diesem Beispiel haben wir Component
(offensichtlich unter Verwendung des Schnittstellenmerkmals der Objektorientierung) als abstrakte Basisklasse. Sowohl Composite
als auch Leaf
implementieren diese Schnittstelle und repräsentieren Containerobjekte bzw. Grundobjekte.
4.3 Implementierung Schritt 1: Definition der abstrakten Komponentenklasse
Diese Methode wird normalerweise in der Schnittstellenklasse definiert und ist eine zentrale Schlüsseloperation.
4.3.1 Definition der Schnittstelle der abstrakten Komponentenklasse
//Component: Grundlegende Komponentenschnittstelle, definiert die Gemeinsamkeiten von Gruppen und individuellen Objekten
type Component interface {
Search(string)
}
4.3.2 Implementieren grundlegender Methoden der abstrakten Komponentenklasse
Dieser Schritt wird speziell in der Containerkomponentenklasse und der Blattkomponentenklasse implementiert.
4.4 Implementierung Schritt 2: Definition der Blattkomponentenklasse
Diese konkrete Klasse repräsentiert die unterste Kategorie oder das unterste Objekt in der Hierarchie und hat keine nächsten Objektschichten.
4.4.1 Ableiten von der abstrakten Komponentenklasse
In Go wird die Schnittstellenvererbung durch die Implementierung von Methoden über Strukturen umgesetzt.
4.4.2 Implementieren von spezifischen Methoden der Blattkomponentenklasse
//Product: Stellt einen Blattknoten dar, d.h. ein Produkt, und kann keine Kindknoten haben
type Product struct {
Name string
}
//Search: Produkte suchen
func (p *Product) Search(keyword string) {
if strings.Contains(p.Name, keyword) {
fmt.Printf("Produkt: '%s' enthält das Schlüsselwort: '%s'\n", p.Name, keyword)
}
}
4.5 Implementierung Schritt 3: Definition der Containerkomponentenklasse
Diese Klasse wird zur Speicherung und Verwaltung von Kindobjekten verwendet und enthält im Allgemeinen einige Methoden zur Verwaltung und Organisation von Kindobjekten, wie add(Component)
, remove(Component)
, etc.
4.5.1 Ableiten von der abstrakten Komponentenklasse
Auch dies wird in Go durch Verwendung von Struct implementiert, um die Schnittstellenmethoden zu implementieren.
4.5.2 Implementierung von Methoden der Containerkomponentenklasse
// Category: Stellt einen Containerknoten dar, d.h. Produktkategorie, die Kindknoten haben kann
type Category struct {
Name string
Children []Component
}
// Hinzufügen: Ein Kindknoten hinzufügen
func (c *Category) Add(child Component) {
c.Children = append(c.Children, child)
}
// Entfernen: Ein Kindknoten entfernen
func (c *Category) Remove(child Component) {
// Spezifische Implementierung ausgelassen
}
// Suche: Produkte suchen
func (c *Category) Search(keyword string) {
fmt.Printf("Kategorie: %s\n", c.Name)
for _, zusammengesetztes := range c.Children {
zusammengesetztes.Search(keyword)
}
}
4.6 Implementierungsschritt 4: Beispiel für Clientcode
Erstellen Sie eine Struktur, fügen Sie sie in eine Baumstruktur ein und rufen Sie dann die Zugriffsfunktion der Baumstruktur auf.
func main() {
root := &Category{Name: "Wurzel"}
electronics := &Category{Name: "Elektronik"}
phone := &Product{Name: "Telefon"}
tv := &Product{Name: "Fernseher"}
root.Add(electronics)
electronics.Add(phone)
electronics.Add(tv)
root.Search("Telefon") // Hier wird in allen Kindern gesucht
}