Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Fabrik, Strategie und Dekorierer

Nach dieser Lektion: Ich kann zu einem Problem eine Fabrik, eine Strategie oder einen Dekorierer wählen und anwenden.

Lektion, 70 Min.4 BefehleLab „Linux im Alltag“: die dreißig Befehle, die Entwickelnde auswendig tippen

Ein Ticketautomat, der viele Fälle kennt

Ein Entwurfsmuster ist eine bewährte Lösung für ein Problem, das im Entwurf von Programmen immer wiederkehrt. Es hat einen Namen, damit Entwickelnde in einem Wort sagen können, was sie meinen.

Ein Ticketautomat erzeugt Fahrkarten, rechnet je nach Tarif und bietet Zusatzleistungen an. Drei Probleme, drei Muster: Fabrik, Strategie und Dekorierer.

Am Ende dieser Lektion

Notiz

Ich kann zu einem Problem eine Fabrik, eine Strategie oder einen Dekorierer wählen und anwenden.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Entwurfsmustereine benannte Lösung für ein wiederkehrendes Entwurfsproblem
Fabrikein Ort, der entscheidet, welches Objekt entstehtticket_fuer("tag")
Strategieein austauschbarer Rechenweg als eigenes Objekt
Dekoriererein Objekt, das ein anderes umhüllt und etwas ergänzt
Umhüllenein Objekt als Teil in ein anderes stecken

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Eine Fabrik entscheidet, welches Objekt entsteht

Das Problem: Ein Programm bekommt einen Text wie "tag" und braucht dazu das richtige Objekt. Steht die Entscheidung an zehn Stellen, ändern Sie bei einer neuen Art zehn Stellen.

Bei der Fabrik liegt die Entscheidung in einer einzigen Funktion. Alle anderen rufen nur ticket_fuer(art) auf und arbeiten mit dem Objekt, das zurückkommt.

Eine Fabrik für Fahrkarten

Code: python
class Einzelfahrt:
    def preis_cent(self):
        return 290

class Tageskarte:
    def preis_cent(self):
        return 780

def ticket_fuer(art):
    if art == "einzel":
        return Einzelfahrt()
    if art == "tag":
        return Tageskarte()
    raise ValueError("Unbekannte Art: " + art)

for art in ["einzel", "tag"]:
    ticket = ticket_fuer(art)
    print(art, ticket.preis_cent())
# Fügen Sie eine dritte Art mit eigenem Preis hinzu.

Eine Strategie macht den Rechenweg austauschbar

Das Problem: Ein Parkhaus rechnet mal pro Stunde, mal mit Tagespauschale. Eine if-Kette in kassieren wächst mit jedem neuen Tarif.

Bei der Strategie wird jeder Rechenweg eine eigene kleine Klasse mit derselben Methode. Das Parkhaus hält einen davon als Teil und ruft ihn auf. Das ist Komposition mit einem Zweck.

Zwei Tarife, ein Parkhaus

Code: python
class Stundentarif:
    def preis_cent(self, stunden):
        return stunden * 200

class Tagespauschale:
    def preis_cent(self, stunden):
        return 900

class Parkhaus:
    def __init__(self, tarif):
        self.tarif = tarif

    def kassieren(self, stunden):
        return self.tarif.preis_cent(stunden)

haus = Parkhaus(Stundentarif())
print(haus.kassieren(3))
haus.tarif = Tagespauschale()
print(haus.kassieren(3))
# Rechnen Sie mit 6 Stunden und vergleichen Sie beide Tarife.

Die drei Muster im Überblick

MusterProblemIdeeBeispiel
FabrikWer entscheidet, welches Objekt entsteht?Eine Funktion wählt die Klasseticket_fuer("tag")
StrategieDer Rechenweg soll wechselnJeder Weg ist ein Objekt mit gleicher MethodeStundentarif, Tagespauschale
DekoriererEine Zusatzleistung ohne neue UnterklasseEin Objekt umhüllt ein anderesMitFahrrad(Einzelfahrt())

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein Dekorierer umhüllt ein Objekt und ergänzt es

Das Problem: Zu einer Fahrkarte kommen Zusatzleistungen wie ein Fahrrad. Für jede Mischung eine Unterklasse zu schreiben, wird schnell unübersichtlich.

Der Dekorierer hat dieselben Methoden wie das Objekt, das er umhüllt. Er ruft es auf und ergänzt das Ergebnis. Das hat nichts mit der @-Schreibweise von Python für Funktionen zu tun. Hier geht es um Objekte.

Eine Fahrkarte mit Fahrrad

Code: python
class Einzelfahrt:
    def preis_cent(self):
        return 290

    def text(self):
        return "Einzelfahrt"

class MitFahrrad:
    def __init__(self, ticket):
        self.ticket = ticket

    def preis_cent(self):
        return self.ticket.preis_cent() + 150

    def text(self):
        return self.ticket.text() + " mit Fahrrad"

ticket = MitFahrrad(Einzelfahrt())
print(ticket.text(), ticket.preis_cent())
# Umhüllen Sie das Ergebnis noch einmal mit MitFahrrad.

Ein häufiger Fehler

Warnung

Viele suchen sich zuerst ein Muster aus und biegen dann das Problem zurecht. Gehen Sie umgekehrt vor: Benennen Sie das Problem, dann prüfen Sie, ob ein Muster passt. Eine Entscheidung mit zwei festen Fällen braucht keine Strategie. Ein einfaches if genügt.

Zwei Hüllen in verschiedener Reihenfolge

Im Lab bauen Sie einen Text und zwei Dekorierer: Doppelt wiederholt den Text, Ausruf hängt ein Ausrufezeichen an.

Dann umhüllen Sie in beiden Reihenfolgen. Die Ausgabe zeigt, dass die Reihenfolge zählt: erst jaja!, dann ja!ja!.

Den Ordner anlegen

Befehl
mkdir -p ~/oop-labor

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Hineingehen

Befehl
cd ~/oop-labor

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Den Text und zwei Hüllen schreiben

Befehl
printf 'class Text:\n    def __init__(self, inhalt):\n        self.inhalt = inhalt\n\n    def lesen(self):\n        return self.inhalt\n\nclass Doppelt:\n    def __init__(self, teil):\n        self.teil = teil\n\n    def lesen(self):\n        return self.teil.lesen() + self.teil.lesen()\n\nclass Ausruf:\n    def __init__(self, teil):\n        self.teil = teil\n\n    def lesen(self):\n        return self.teil.lesen() + "!"\n\nprint(Ausruf(Doppelt(Text("ja"))).lesen())\nprint(Doppelt(Ausruf(Text("ja"))).lesen())\n' > huellen.py

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das Programm starten

Befehl
python3 huellen.py

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Die Reihenfolge der Hüllen ändert das Ergebnis

Im ersten Fall wird zuerst verdoppelt, dann kommt das Ausrufezeichen: jaja!. Im zweiten Fall hat jede Hälfte ein Ausrufezeichen: ja!ja!.

Jede Hülle sieht nur das Objekt direkt in ihr. Deshalb lassen sich Hüllen frei kombinieren, solange alle lesen anbieten.

Über dieses Lab und seinen Quellcode: Lab „Linux im Alltag“: die dreißig Befehle, die Entwickelnde auswendig tippen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.