Menu
Coddy logo textTech

Einführung in Entwurfsmuster

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 85 von 107.

Entwurfsmuster sind wiederverwendbare Lösungen für häufige Probleme, die beim Softwareentwurf auftreten. Sie sind kein Code, den du direkt kopierst, sondern vielmehr Vorlagen, die dich dabei unterstützen, deine Typen und ihre Interaktionen zu strukturieren, um bestimmte Herausforderungen zu bewältigen.

Entwurfsmuster werden typischerweise in drei Kategorien gruppiert:

KategorieZweckBeispiele
ErzeugungsmusterMechanismen zur ObjekterzeugungSingleton, Factory, Builder
StrukturmusterZusammensetzen von Typen zu größeren StrukturenAdapter, Decorator, Composite
VerhaltensmusterKommunikation zwischen ObjektenObserver, Strategy, Command

In Go sehen Entwurfsmuster anders aus als in traditionellen OOP-Sprachen.

Ohne Klassen oder Vererbung implementiert Go Muster mithilfe von Schnittstellen, Struktur-Einbettung und Komposition. Wo Java möglicherweise eine abstrakte Klasse verwenden würde, nutzt Go eine Schnittstelle. Wo C++ möglicherweise Vererbung verwenden würde, nutzt Go Einbettung.

Das Erlernen von Mustern hilft dir, häufige Probleme zu erkennen und Lösungen effektiv mit anderen Entwicklerinnen und Entwicklern zu kommunizieren. Wenn jemand erwähnt: „Verwende hier das Strategy-Muster“, versteht das gesamte Team den Ansatz ohne lange Erklärungen.

In den nächsten Lektionen wirst du mehrere grundlegende Muster in Go implementieren, angefangen mit Erzeugungsmustern wie Singleton und Factory und anschließend mit Verhaltensmustern wie Observer und Strategy.

challenge icon

Aufgabe

Einfach

Erstellen wir ein einfaches Benachrichtigungssystem, das zeigt, wie Design Patterns dabei helfen, Code zu organisieren! Du wirst eine Struktur erstellen, die in zukünftigen Lektionen problemlos um Muster wie Observer oder Strategy erweitert werden könnte. Konzentriere dich zunächst jedoch darauf, saubere Schnittstellen und Typen einzurichten, die guten OOP-Prinzipien folgen.

Du wirst deinen Code auf drei Dateien verteilen:

  • notifier.go: Definiere die zentrale Schnittstelle und die Typen für dein Benachrichtigungssystem.

    Erstelle eine Notifier-Schnittstelle mit einer einzigen Methode Send(message string) string, die eine Bestätigungsnachricht zurückgibt.

    Implementiere zwei konkrete Benachrichtigungstypen:

    • EmailNotifier mit einem Address-Feld. Seine Send-Methode gibt Email to [address]: [message] zurück
    • SMSNotifier mit einem PhoneNumber-Feld. Seine Send-Methode gibt SMS to [phone]: [message] zurück
  • dispatcher.go: Erstelle einen Dispatcher, der über die Schnittstelle mit jedem Benachrichtigungstyp funktioniert.

    Erstelle eine NotificationDispatcher-Struktur, die ein Slice von Notifier-Schnittstellen enthält. Füge diese Methoden hinzu:

    • AddNotifier(n Notifier), um einen Benachrichtigungstyp zu registrieren
    • Broadcast(message string) []string, die die Nachricht über alle registrierten Benachrichtigungstypen sendet und ein Slice mit allen Bestätigungszeichenfolgen zurückgibt

    Erstelle außerdem einen NewNotificationDispatcher()-Konstruktor, der einen initialisierten Dispatcher zurückgibt.

  • main.go: Richte die Benachrichtigungstypen ein und sende Nachrichten an alle.

    Lies die Anzahl der zu erstellenden Benachrichtigungstypen ein. Lies für jeden Benachrichtigungstyp dessen Art (email oder sms) und sein Ziel (Adresse oder Telefonnummer) ein. Füge jeden Typ einem Dispatcher hinzu.

    Lies anschließend eine Nachricht ein, die an alle gesendet werden soll. Sende sie über alle Benachrichtigungstypen und gib jede Bestätigung in einer eigenen Zeile aus.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Anzahl der Benachrichtigungstypen
  • Für jeden Benachrichtigungstyp: Art (email oder sms), dann Ziel
  • Letzte Zeile: Nachricht, die an alle gesendet werden soll

Zum Beispiel bei folgender Eingabe:

3
email
alice@example.com
sms
555-1234
email
bob@example.com
Server maintenance at midnight

Deine Ausgabe sollte folgendermaßen aussehen:

Email to alice@example.com: Server maintenance at midnight
SMS to 555-1234: Server maintenance at midnight
Email to bob@example.com: Server maintenance at midnight

Und bei folgender Eingabe:

2
sms
555-9999
sms
555-0000
Meeting canceled

Deine Ausgabe sollte folgendermaßen aussehen:

SMS to 555-9999: Meeting canceled
SMS to 555-0000: Meeting canceled

Diese Struktur zeigt, wie Schnittstellen flexible und erweiterbare Designs ermöglichen. Der Dispatcher weiß nichts über bestimmte Benachrichtigungstypen. Er weiß nur, dass sie Send aufrufen können. Das ist die Grundlage, auf der Muster wie Observer und Strategy aufbauen!

Probier es selbst

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Lese die Anzahl der Notifier
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	// Erstelle einen neuen Dispatcher
	dispatcher := NewNotificationDispatcher()

	// Lese jeden Notifier und füge ihn zum Dispatcher hinzu
	for i := 0; i < count; i++ {
		notifierType, _ := reader.ReadString('\n')
		notifierType = strings.TrimSpace(notifierType)

		destination, _ := reader.ReadString('\n')
		destination = strings.TrimSpace(destination)

		// TODO: Erstelle den passenden Notifier basierend auf dem Typ
		// und füge ihn zum Dispatcher hinzu
		// Hinweis: Prüfe, ob notifierType "email" oder "sms" ist

	}

	// Lese die zu übertragende Nachricht
	message, _ := reader.ReadString('\n')
	message = strings.TrimSpace(message)

	// TODO: Übertrage die Nachricht und gib jede Bestätigung aus

}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Go-Compiler