Python-Vermittlermuster
Das Mediator-Muster ist ein Verhaltensentwurfsmuster, das direkte Kommunikationsabhängigkeiten zwischen Objekten reduziert, indem ein Mediator-Objekt eingeführt wird. Stellen Sie sich einen Flughafen-Kontrollturm im wirklichen Leben vor – alle Flugzeuge kommunizieren nicht direkt miteinander, sondern koordinieren Starts, Landungen und Routen über den Kontrollturm, wodurch Chaos und Konflikte vermieden werden.
Wenn in der Softwareentwicklung komplexe Interaktionsbeziehungen zwischen mehreren Objekten bestehen, kann das Mediator-Muster diese Interaktionen im Mediator kapseln und dadurch die Kopplung zwischen Objekten reduzieren.
Kernidee
Die Kernidee des Mediator-Musters ist„Sprich nicht direkt; koordiniere über einen Mediator.“Es löst die Komplexität von Viele-zu-viele-Interaktionen zwischen Objekten und macht das System einfacher zu warten und zu erweitern.
Warum brauchen wir das Mediator-Muster?
Problemszenario
Angenommen, wir entwickeln ein Chatroom-System mit mehreren Benutzern, die sich gegenseitig Nachrichten senden müssen. Ohne einen Mediator könnte der Code so aussehen:
Beispiel
def __init__(self, name):
self.name = name
self.other_users = [] # Muss alle anderen Benutzer kennen
def send_message(self, message, to_user):
print(f"{self.name} hat an {to_user.name} gesendet: {message}")
to_user.receive_message(message, self)
def receive_message(self, message, from_user):
print(f{self.name} hat eine Nachricht von {from_user.name} erhalten: {message})
# Verwendungsbeispiel
user1 = User(Xiaoming)
user2 = User(Xiaohong)
user3 = User(Xiaogang)
# Jeder Benutzer muss alle anderen Benutzer kennen
user1.other_users = [user2, user3]
user2.other_users = [user1, user3]
user3.other_users = [user1, user2]
user1.send_message(Hallo!, user2)
Nachteile dieses Entwurfs:
- Hohe Kopplung zwischen Objekten; jeder Benutzer muss alle anderen Benutzer kennen.
- Das Hinzufügen eines neuen Benutzers erfordert die Änderung aller vorhandenen Benutzer.
- Schwer zu warten; die Interaktionslogik ist über Objekte verstreut.
Lösung
Das Mediator-Muster löst dieses Problem durch die Einführung eines Chatraums (Mediator):
Beispiel
def __init__(self):
self.users = {}
def register_user(self, user):
self.users[user.name] = user
user.chat_room = self
def send_message(self, message, from_user, to_user_name=Keine):
if to_user_name: # Privater Chat
if to_user_name in self.users:
self.users[to_user_name].receive_message(message, from_user)
else: # Gruppenchat
for user_name, user in self.users.items():
if user_name != from_user.name:
user.receive_message(message, from_user)
class User:
def __init__(self, name):
self.name = name
self.chat_room = None
def send_message(self, message, to_user_name=None):
if self.chat_room:
self.chat_room.send_message(message, self, to_user_name)
def receive_message(self, message, from_user):
print(f{self.name} hat eine Nachricht von {from_user.name} erhalten: {message})
# Verwendungsbeispiel
chat_room = ChatRoom()
user1 = User(Xiaoming)
user2 = User(Xiaohong)
user3 = User(Xiaogang)
chat_room.register_user(user1)
chat_room.register_user(user2)
chat_room.register_user(user3)
user1.send_message(Hallo zusammen!) # Broadcast-Nachricht
user2.send_message(Hallo Xiaoming!, Xiaoming) # Privater Chat
Implementierung des Mediator-Musters
Grundstruktur
Lassen Sie uns die Implementierung des Mediator-Musters anhand eines vollständigeren Beispiels verstehen:
Beispiel
from typing import List
# Abstrakter Mediator
class Mediator(ABC):
@abstractmethod
def notify(self, sender: object, event: str, data: dict = None):
pass
# Konkreter Mediator - Chatraum
class ChatRoomMediator(Mediator):
def __init__(self):
self.users: List[User] = []
def add_user(self, user):
self.users.append(user)
user.set_mediator(self)
def notify(self, sender, event, data=Keine):
if event == "send_message":
message = data.get("message")
target_user = data.get("target_user")
if target_user: # Privater Chat
for user in self.users:
if user.name == target_user:
user.receive_message(message, sender.name)
else: # Gruppenchat
for user in self.users:
if user != sender:
user.receive_message(message, sender.name)
elif event == "user_joined":
message = fSystem: {sender.name} ist dem Chatraum beigetreten
for user in self.users:
if user != sender:
user.receive_message(message, System)
# Basis-Komponenten-Klasse
class BaseComponent:
def __init__(self):
self._mediator = None
def set_mediator(self, mediator: Mediator):
self._mediator = mediator
# Konkrete Komponente - Benutzer
class User(BaseComponent):
def __init__(self, name):
super().__init__()
self.name = name
def send_message(self, message, target_user=None):
print(f{self.name} hat eine Nachricht gesendet: {message})
self._mediator.notify(self, "send_message", {
"message": message,
"target_user": target_user
})
def join_chat(self):
self._mediator.notify(self, "user_joined")
def receive_message(self, message, from_name):
print(f{self.name} hat eine Nachricht von {from_name} empfangen: {message})
# Verwendungsbeispiel
def main():
# Den Mediator erstellen
chat_room = ChatRoomMediator()
# Benutzer erstellen
alice = Benutzer("Alice")
bob = Benutzer("Bob")
charlie = Benutzer("Charlie")
# Benutzer beim Chatraum registrieren
chat_room.add_user(alice)
chat_room.add_user(bob)
chat_room.add_user(charlie)
print(=== Chatraum-Demo ===)
# Alice tritt dem Chatraum bei
alice.join_chat()
# Nachricht senden
alice.send_message(Hallo zusammen, ich bin Alice!)
bob.send_message(Willkommen Alice!)
charlie.send_message(Hallo Alice!, "Alice") # Privater Chat
# Bob sendet eine Gruppennachricht
bob.send_message(Ist jemand online?)
if __name__ == "__main__":
main()
Ausgabe
=== 聊天室演示 === 系统: Alice 加入了聊天室 Alice 发送消息: 大家好,我是 Alice! Bob 收到来自 Alice 的消息: 大家好,我是 Alice! Charlie 收到来自 Alice 的消息: 大家好,我是 Alice! Bob 发送消息: 欢迎 Alice! Alice 收到来自 Bob 的消息: 欢迎 Alice! Charlie 收到来自 Bob 的消息: 欢迎 Alice! Charlie 发送消息: Alice 你好! Alice 收到来自 Charlie 的消息: Alice 你好! Bob 发送消息: 有人在线吗? Alice 收到来自 Bob 的消息: 有人在线吗? Charlie 收到来自 Bob 的消息: 有人在线吗?
UML-Struktur des Mediator-Musters

Strukturbeschreibung
- Mediator (Mediator-Schnittstelle): definiert die Kommunikationsschnittstelle
- ConcreteMediator (konkreter Mediator): implementiert die Koordinationslogik und kennt alle Komponenten
- BaseComponent (Basiskomponente): enthält eine Referenz auf den Mediator
- ConcreteComponent (konkrete Komponente): implementiert konkrete Geschäftslogik
Anwendungsszenarien aus der Praxis
Szenario 1: GUI-Anwendung
In einer grafischen Benutzeroberfläche koordinieren verschiedene Steuerelemente (Schaltflächen, Textfelder, Kontrollkästchen usw.) Interaktionen über einen Mediator:
Beispiel
def __init__(self):
self.login_button = None
self.username_input = None
self.password_input = None
self.remember_checkbox = None
def notify(self, sender, event):
if event == "username_changed" or event == "password_changed":
# Wenn Benutzername oder Passwort eingegeben wird, prüfen, ob die Anmeldeschaltfläche aktiviert werden kann
username = self.username_input.get_text()
password = self.password_input.get_text()
self.login_button.set_enabled(bool(username and Passwort))
elif event == "login_clicked":
# Login-Logik behandeln
username = self.username_input.get_text()
password = self.password_input.get_text()
remember = self.remember_checkbox.is_checked()
print(fAnmeldung: {username}, Angemeldet bleiben: {remember})
elif event == "remember_changed":
print(Option 'Angemeldet bleiben' geändert)
class UIComponent:
def __init__(self, mediator=None):
self.mediator = mediator
def set_mediator(self, mediator):
self.mediator = mediator
class Button(UIComponent):
def click(self):
if self.mediator:
self.mediator.notify(self, "login_clicked")
def set_enabled(self, enabled):
print(fButton {'Aktivieren' if enabled else 'Deaktivieren'})
class TextInput(UIComponent):
def __init__(self, mediator=None):
super().__init__(mediator)
self._text = ""
def set_text(self, text):
self._text = text
if self.mediator:
self.mediator.notify(self, "username_changed")
def get_text(self):
return self._text
# Verwendungsbeispiel
dialog = DialogMediator()
login_btn = Button()
username_input = TextInput()
password_input = TextInput()
dialog.login_button = login_btn
dialog.username_input = username_input
dialog.password_input = password_input
login_btn.set_mediator(dialog)
username_input.set_mediator(dialog)
password_input.set_mediator(dialog)
# Benutzereingabe simulieren
username_input.set_text("user123")
password_input.set_text("pass123")
login_btn.click()
Szenario 2: E-Commerce-Bestellsystem
In einem E-Commerce-System umfasst die Auftragsabwicklung mehrere Teilsysteme wie Bestandsverwaltung, Zahlung und Logistik:
Beispiel
def __init__(self):
self.inventory_system = None
self.payment_system = None
self.shipping_system = None
self.notification_system = None
def place_order(self, order_data):
print(=== Bestellverarbeitung starten ===)
# Lagerbestand prüfen
if not self.inventory_system.check_stock(order_data):
return Unzureichender Bestand
# Zahlung verarbeiten
payment_result = self.payment_system.process_payment(order_data)
if not payment_result:
return Zahlung fehlgeschlagen
# Lagerbestand aktualisieren
self.inventory_system.update_stock(order_data)
# Versand veranlassen
shipping_info = self.shipping_system.schedule_delivery(order_data)
# Benachrichtigung senden
self.notification_system.send_confirmation(order_data, shipping_info)
return Bestellung erfolgreich verarbeitet
class InventorySystem:
def check_stock(self, order_data):
print(Lagerbestand wird geprüft...)
return True
def update_stock(self, order_data):
print(Lagerbestand wird aktualisiert...)
class PaymentSystem:
def process_payment(self, order_data):
print(Zahlung wird verarbeitet...)
return True
class ShippingSystem:
def schedule_delivery(self, order_data):
print(Versand wird arrangiert...)
return Sendungsverfolgungsnummer: SF123456789
class NotificationSystem:
def send_confirmation(self, order_data, shipping_info):
print(fBestätigungs-E-Mail senden, Versandinformationen: {shipping_info})
# Verwendungsbeispiel
mediator = OrderMediator()
mediator.inventory_system = InventorySystem()
mediator.payment_system = PaymentSystem()
mediator.shipping_system = ShippingSystem()
mediator.notification_system = NotificationSystem()
order_data = {"product_id": "123", "quantity": 2, "user_id": "user001"}
result = mediator.place_order(order_data)
print(fBestellergebnis: {result})
Vor- und Nachteile des Mediator-Musters
Vorteile
| Vorteile | Beschreibung |
|---|---|
| Prinzip der einzigen Verantwortung | Zentralisiert die Interaktionslogik zwischen Komponenten im Mediator. |
| Open/Closed-Prinzip | Ermöglicht die Einführung neuer Mediatoren, ohne bestehende Komponenten zu ändern. |
| Reduziert Kopplung | Reduziert direkte Abhängigkeiten zwischen Komponenten. |
| Einfache Wiederverwendung | Einzelne Komponenten können in verschiedenen Kontexten leichter wiederverwendet werden. |
Nachteile
| Nachteile | Beschreibung |
|---|---|
| Der Mediator kann komplex werden | Mit zunehmender Interaktionslogik kann der Mediator zu einem Gott-Objekt werden. |
| Performance-Overhead | Die gesamte Kommunikation läuft über den Mediator, was einen Leistungsengpass verursachen kann. |
| Schwierig zu debuggen | Die Interaktionslogik ist im Mediator konzentriert, daher kann das Debugging die Verfolgung mehrerer Komponenten erfordern. |
Best Practices und Überlegungen
1. Verantwortlichkeiten des Mediators sinnvoll aufteilen
Lassen Sie nicht zu, dass ein einziger Mediator alles übernimmt; Sie können mehrere Mediatoren nach Geschäftsdomänen aufteilen:
Beispiel
def notify(self, sender, event, data):
if event == "user_registered":
# Logik nach der Benutzerregistrierung behandeln
self.send_welcome_email(data)
self.create_user_profile(data)
self.add_to_mailing_list(data)
class OrderProcessingMediator:
def notify(self, sender, event, data):
if event == "order_created":
# Logik nach der Bestellerstellung behandeln
self.validate_order(data)
self.process_payment(data)
self.update_inventory(data)
2. Vermeiden Sie einen übermäßig komplexen Mediator
Wenn der Mediator zu komplex wird, sollten Sie andere Muster oder Refactoring in Betracht ziehen:
Beispiel
class ComplexMediator:
def handle_event(self, event_type, data):
if event_type == "user_action":
# Eine Menge komplexer Geschäftslogik...
pass
elif event_type == "system_event":
# Komplexere Logik...
pass
# Gute Praxis - Verwenden Sie das Strategiemuster, um komplexe Logik zu zerlegen
class EventHandler:
def handle(self, data):
pass
class UserActionHandler(EventHandler):
def handle(self, data):
# Benutzeraktionen gezielt behandeln
pass
class SimpleMediator:
def __init__(self):
self.handlers = {}
def register_handler(self, event_type, handler):
self.handlers[event_type] = handler
def notify(self, event_type, data):
if event_type in self.handlers:
self.handlers[event_type].handle(data)
3. Kombination mit dem Observer-Muster in Betracht ziehen
Das Mediator-Muster wird oft in Kombination mit dem Observer-Muster verwendet:
Beispiel
from typing import List
class Observer(ABC):
@abstractmethod
def update(self, event, data):
pass
class Observable:
def __init__(self):
self._observers: List[Observer] = []
def add_observer(self, observer):
self._observers.append(observer)
def notify_observers(self, event, data=None):
for observer in self._observers:
observer.update(event, data)
class ChatMediator(Observable):
def send_message(self, message, sender, receiver=Keine):
# Mediator-Logik
event_data = {
"message": message,
"sender": sender,
"receiver": receiver
}
self.notify_observers("message_sent", event_data)
class LoggingObserver(Observer):
def update(self, event, data):
if event == "message_sent":
print(fProtokoll: {data['sender']} hat eine Nachricht gesendet)
Übungsaufgaben
Übung 1: Verbessern Sie ein Chatraum-System
Erweitern Sie das vorherige Chatraum-System und fügen Sie die folgenden Funktionen hinzu:
- Unterstützen Sie die Erstellung mehrerer Chaträume
- Unterstützen Sie Benutzer beim Wechseln zwischen verschiedenen Chaträumen.
- Fügen Sie Administratorfunktionen hinzu (Benutzer kicken, stummschalten usw.)
Übung 2: Entwerfen Sie ein Flugticket-Buchungssystem
Verwenden Sie das Mediator-Muster, um ein Flugticket-Buchungssystem zu entwerfen, das die folgenden Komponenten enthält:
- Flugabfrage
- Sitzplatzauswahl
- Zahlungsabwicklung
- Ticketgenerierung
- Benachrichtigungsversand
Die Komponenten müssen über den Mediator koordiniert zusammenarbeiten.
Übung 3: Smart-Home-Steuerungssystem
Entwerfen Sie ein Smart-Home-Steuerungssystem, das Folgendes umfasst:
- Beleuchtungssteuerung
- Temperaturregelung
- Sicherheitsüberwachung
- Szenenmodus
Implementieren Sie eine intelligente geräteübergreifende Verknüpfung über den Mediator.
Zusammenfassung
Das Mediator-Muster ist ein leistungsstarkes Werkzeug für den Umgang mit komplexen Objektinteraktionen. Es vereinfacht die Systemarchitektur durch die Einführung eines Koordinationszentrums und eignet sich besonders für die folgenden Szenarien:
- Zwischen Objekten bestehen komplexe vernetzte Interaktionsbeziehungen
- Wenn die Interaktionslogik zwischen mehreren Objekten zentral gesteuert werden muss
- Kopplung zwischen Objekten reduzieren möchten
Denken Sie daran: Das Mediator-Muster ist kein Allheilmittel. Wenn die Interaktionslogik einfach ist, kann die direkte Kommunikation von Objekt zu Objekt geeigneter sein. Bei komplexen Systemen kann jedoch der richtige Einsatz des Mediator-Musters die Wartbarkeit und Erweiterbarkeit des Codes erheblich verbessern.
Wichtige Punkte:
- Der Mediator kapselt die Interaktionslogik zwischen Objekten
- Komponenten kommunizieren nur mit dem Mediator und sind nicht direkt voneinander abhängig
- Der Mediator kann komplex werden und erfordert ein sorgfältiges Design
- Die Kombination mit anderen Mustern (wie Observer) kann bessere Ergebnisse erzielen