Skip to content

Abstract Factory Pattern

Factory method patternde sınıfların oluşturulmasını ve bunların alt sınıfları tarafından özelleştirilmesine olanak sağlayan arayüzler oluşturduğunu yani, temelde bir sınıfın nesnelerini yaratan bir metod sağladığını ve bu metodun, alt sınıflar tarafından yeniden tanımlanabildiğini, bu sayede de, bir üst sınıfın nesnelerinin yaratılmasında alt sınıfların ne gibi özellikler kazanacağı belirlenebildiğini görmüştük.

Abstract factory pattende ise temel amaç sınıfların yaratılmasına yönelik arayüzler sağlamaktır. factory method’da olduğu gibi bir sınıfın nesnelerinin yaratılmasını kontrol etmez, fakat bir grup nesnenin bir arada yaratılmasına izin verir. Bu sayede, birbirleriyle uyumlu nesne gruplarının yaratılması kolaylaşır. Özetle, Factory Method, tek bir nesne yaratmayı özelleştirirken, Abstract Factory, bir grup nesne yaratmayı özelleştirir.

Bir örnek üzerinden açıklayarak gidecek olursak, Bir restoran sahibi olduğumuzu düşünelim ve restoranımızdaki fix menümüz olsun menümüz çorba, ana yemek ve tatlıdan oluşuyor ve menümüzün vejateryan ve vegan alternatifleride mevcut, farklı beslenme tipleri için farklı menülerdeki yemekleri hazırlamak farklı süreçler, malzemeler vs. gerektiriyor olacak bu senaryoyu koda aktarıp müşteri resporanımıza gelip sipariş verdiğinde yemeğini hazırlamak için abstract factory patterni kullanarak bir sistem tasarlayabiliriz. Öncelikle tüm menülerimizde yer alan çorba, ana yemek ve tatlı için abstract factory classını şöyle oluşturabiliriz.

from abc import ABC, abstractmethod

class AbstractFactory(ABC):
    
    @abstractmethod
    def make_soup(self):
        pass
    
    @abstractmethod
    def make_main_dish(self):
        pass
    
    @abstractmethod
    def make_dessert(self):
        pass

Farklı beslenme tipleri için menülerimizi oluşturan factory sınıflarını oluşturalım.

class StandardFactory(AbstractFactory):
    def make_soup(self):
        return "Fish Soup"
    
    def make_main_dish(self):
        return "Adana Kebab"
    
    def make_dessert(self):
        return "Baklava"


class VegetarianFactory(AbstractFactory):
    def make_soup(self):
        return "Vegatable Soup"
    
    def make_main_dish(self):
        return "Lentil Burger"
    
    def make_dessert(self):
        return "Coconut Date Balls"


class VeganFactory(AbstractFactory):
    def make_soup(self):
        return "Onion soup"
    
    def make_main_dish(self):
        return "Vegan Pizza"
    
    def make_dessert(self):
        return "Vegan Brownie"

Müşterinin seçtiği yemeğe göre hangi factory sınıfının kullanıcağını belirleyen management görevini üstlenecek restaurant sınıfımızı yazalım ve hangi menünün istendiğini seçilebilecek basit bir yapı kuralım.

class Restaurant(object):
    def __init__(self, factory):
        self.factory = factory
        
    def order_menu(self):
        soup = self.factory.make_soup()
        main_dish = self.factory.make_main_dish()
        dessert = self.factory.make_dessert()
        
        print(f"Soup: {soup}, Main Dish: {main_dish}, Dessert: {dessert} - Bon Appetit")

if __name__ == "__main__":
    print("Please select your order")
    menu = input("Please select your order \n 1- Standard  \n 2- Vegetarian  \n 3- Vegan \n")
    factory = None
    if menu == "1":
        factory = StandardFactory()
    elif menu == "2":
        factory = VegetarianFactory()
    elif menu == "3":
        factory = VeganFactory()
    else:
        print("Exited")
        
    restaurant = Restaurant(factory)
    order = restaurant.order_menu()
        
-----------------------------------------------------------------------
Output:
1 - Soup: Fish Soup, Main Dish: Adana Kebab, Dessert: Baklava - Bon Appetit
2 - Soup: Vegatable Soup, Main Dish: Lentil Burger, Dessert: Coconut Date Balls - Bon Appetit
3- Soup: Onion soup, Main Dish: Vegan Pizza, Dessert: Vegan Brownie - Bon Appetit

Sonuç olarak müşterinin seçtiği beslenme alışkanlığına göre farklı yemekler hazırlayacak ve siparişi müşteriye sunacak yapıyı abstract factory pattern pattern uygulayarak kurmuş olduk.

Ayrıca kurduğumuz bu yapı SOLID prensiplerinden,

Single Responsibility prensibine uygun, prensip kısaca bir sınıfın/metodun yalnızca bir sorumluluğu olması gerektiğini belirtir. abstract factory tasarım kalıbı, bu prensibe uygun bir yaklaşım sunar. Her factory sınıfının tek bir sorumluluğu vardır ve yalnızca kendi sorumluluğunu yerine getirmektedir.

Liskov Substitution prensibine uygun, prensip kısaca alt sınıfların üst sınıfların yerine geçebilmesi gerektiğini belirtir. abstract factoryde alt sınıfların bir arayüz aracılığıyla üst sınıfların yerine geçebilmesini sağlar, bu sayede de yaratılan nesnelerin, farklı alt sınıflar tarafından oluşturulması mümkündür ve bu nesneler, üst sınıfların yerine geçebilir.

Open-open prensibne uygun, prensip kısaca bir sınıfın değişikliğe kapalı, ancak geliştirmeye açık olması gerektiğini belirtir. abstract factory, yeni bir nesne yaratmak için sınıf değişikliği yapmaya gerek kalmadan, yeni bir factory sınıfı oluşturulması ile geliştirme sağlanabilir. bu sayede, mevcut kodda değişiklik yapmadan, yeni bir nesne grubu yaratmak mümkündür.

gibi prensipleri açıkca karşılamaktadır, öte yandan ise her nesne grubunu yaratmak için kendine ait bir factory sınıfı olması gerektiğinden karmaşıklığı artırabilir, abstract factory arayüzü sadece bir nesne gurubuyla ilgilenecek/çalışacak şekilde tasarlandığından, farklı nesne gruplarıyla ilgili işlemler yapılmak istendiğinde veya varolan gruba yeni bir nesne eklendiğinde, değişiklik yapmak daha zor hale gelecektir.


Sources:

Published inCreational Design PatternsDesign Patterns

Be First to Comment

Leave a Reply

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