Skip to content

Mediator Pattern

Behavioral design patternlerden biri olan mediator patternin temel amacı nesneler arasındaki karmaşık iletişim sürecinin ortak bir nesne üzerinden yürümesini sağlayarak bağımlılığı azaltmak, sadeleştirmek ve daha yönetilebilir hale getirmektir. Tasarım kalıbı için verilen çok güzel bir gerçek hayat örneği var genelde her yerde bu örneği görürüz şöyleki, bir hava limanı düşünün bir çok uçak iniş veya kalkış yapıyor, iletişim ise her zaman kule üzerinden gerçekleşiyor, talimatlar kuleden veriliyor veya talimatları sadece kule alıyor, bir uçak başka bir uçakla asla iletişime geçmiyor, işte bu organizasyondaki kule tüm iletişim sürecinin üzerinden yürüdüğü mediator oluyor.

Mediator patternin, özellikle büyük ve karmaşık sistemlerde kullanışlılığı ve faydasını görmek daha kolaydır. Sistemin ölçeklenebilirliğini artırır ve bakımını kolaylaştırır. Aynı zamanda nesneler arasındaki bağımlılıkları azalttığından, kodun yeniden kullanılabilirliğinide (reusability) artırır. Single Responsibility ve Open-open prensiplerinden yola çıkacak olursak her sınıf veya method tek bir görevi yerine getirmeli, aynı zamanda değişime kapalı ama gelişime açık olmalı, bu noktada single responsibility için yapılarımızı ayırdığımızda birim sayısı artacaktır, buna bağlı olarakta bu birimlerin aralarındaki iletişim oklarının sayısı, karmaşıklığı ve bağımlılığıda artaracağından, günün sonunda bir sınıfın bir methodu veya kendisi değiştirilmek istendiğinde bir çok kısmı incelemek gerekecekti ve geliştirme maliyeti yükselerek open-open’a ters düşecekti, mediator bu noktada yeniden kullanılabilirlik, modülerlik ve esnekliği artırmış oluyor.

https://www.dofactory.com/img/diagrams/net/mediator.png

Mediator tasarım deseninin diagramını incelediğimizde bir Mediator arayüzü görüyoruz. Bu arayüz veya sınıf, nesnelerle iletişim için yöntemleri tanımlar. Her nesne, diğer nesnelerle iletişim kurmak için Mediator’a kaydedilir ve Mediator, kayıtlı nesnelerin listesini tutar. Bir nesne, başka bir nesneyle iletişim kurmak istediğinde, bir mesajı Mediator’a gönderir ve Mediator, mesajı uygun nesneye iletir. Colleague nesnesi ise bir birleriyle iletişim kuracak somut sınıfların uygulayacağı arayüzü belirtiyor.

Örnek bir senaryo üzerinden kodlayacak olursa: bir uçuş rezervasyon sistemi yazdığımızı düşünelim. Bu sistemin Mediator sınıfı, uçuşlar arasındaki iletişimi yönetirken, Colleague sınıfları ise yolcu ve uçuş gibi nesneleri temsil ediyor olsun. Kısacası uçuşlar ile yolcuların rezervasyon işlemlerini mediator pattern ile gerçekleştirelim.

from abc import ABC, abstractmethod


class FlightMediator(ABC):
    @abstractmethod
    def book_seat(self, flight, passenger):
        pass


class ConcreteFlightMediator(FlightMediator):
    def __init__(self):
        self.flights = []
        self.passengers = {}

    def register_flight(self, flight):
        self.flights.append(flight)

    def register_passenger(self, passenger):
        self.passengers[passenger.name] = passenger

    def book_seat(self, flight, passenger):
        if flight in self.flights and passenger in self.passengers.values():
            print(f"# Booking seat for {passenger.name} on {flight.flight_number}")
            flight.book_seat(passenger)


class Flight:
    def __init__(self, flight_number, capacity):
        self.flight_number = flight_number
        self.capacity = capacity
        self.passengers = set()

    def book_seat(self, passenger):
        if len(self.passengers) < self.capacity:
            self.passengers.add(passenger)
            print(f"+ Seat booked for {passenger.name} on flight {self.flight_number}")
        else:
            print(f"- No available seats on flight {self.flight_number}")


class Passenger:
    def __init__(self, name):
        self.name = name


if __name__ == '__main__':
    mediator = ConcreteFlightMediator()

    flight1 = Flight("ABC123", 3)
    flight2 = Flight("DEF456", 2)

    mediator.register_flight(flight1)
    mediator.register_flight(flight2)

    alice = Passenger("Alice")
    bob = Passenger("Bob")
    charlie = Passenger("Charlie")

    mediator.register_passenger(alice)
    mediator.register_passenger(bob)
    mediator.register_passenger(charlie)

    mediator.book_seat(flight1, alice)
    mediator.book_seat(flight1, bob)
    mediator.book_seat(flight1, charlie)
    mediator.book_seat(flight2, alice)
    mediator.book_seat(flight2, bob)
    mediator.book_seat(flight2, charlie)

-----------------------------------------------------------------------
Output:

# Booking seat for Alice on ABC123
+ Seat booked for Alice on flight ABC123
# Booking seat for Bob on ABC123
+ Seat booked for Bob on flight ABC123
# Booking seat for Charlie on ABC123
+ Seat booked for Charlie on flight ABC123
# Booking seat for Alice on DEF456
+ Seat booked for Alice on flight DEF456
# Booking seat for Bob on DEF456
+ Seat booked for Bob on flight DEF456
# Booking seat for Charlie on DEF456
- No available seats on flight DEF456

FlightMediator arayüzü, aracı nesneyi (Mediator) temsil eder. ConcreteFlightMediator sınıfı ise, Flight ve Passenger nesneleri (Colleague nesneleri) book_seat metodunu çağırdığında, birbirine bağlayarak rezervasyon işlemlerinin gerçekleştirilmesini sağlar. Günün sonunda sisteme yeni bir Flight veya Passenger nesnesi eklendiğinde, bunları ConcreteFlightMediator sınıfına register etmek yeterli olacaktır.

Mediator tasarım desenini uygularken dikkat edilmesi gereken hususlardan en önemlisi bir çok nesnenin iletişimi sağlanırken karmaşık ve büyük mediator nesneleri oluşma ihtimali vardır bu durumda bakım ve geliştirme maliyetleride doğrudan artıyor olacaktır, aynı zamanda nesneler arasındaki iletişime ara bir katman giriyor olacağından belirli bir aşamada performansı düşürebilir, bu takası göze alıp hesaplayarak (performans x karmaşıklık) mediator patternin uygulanması faydalı olacaktır.


Published inBehavioral Design PatternsDesign Patterns

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *