Creational tasarım desenlerinden biri olan factory method design pattern, en temel ve basit anlamda, objelerin örneğini oluşturma sorumluluğunu başka bir objeye devrederek, tüm bu örnek oluşturma sürecinin ortak bir obje üzerinden yürütüldüğü tasarım kalıbıdır diyebiliriz. Temelde odaklandığı ve problem; uygulamanıza gelecekte eklenecek yöntemlerin karmaşık koşul/şart yapılarından arındırılarak, tüm bu yöntemlerin tek bir noktadan yönetilmesini, sınırlılıklarının belirlenmesini ve uygulanabilmesini sağlar, factory method sayesinde objeleri kullanan yapı ve objeleri oluşturan yapı birbirinden ayrılacağından, bakım ve geliştirme maliyeti makul yapılar kurabiliriz. Çalıştığınız projede verilerin .txt formatında dışarı aktarılmasını sağlayan bir geliştirme yaptığınızı düşünün, verilerin .txt halinde dışarı aktarılması sağlamak için TextExporter sınıfı oluşturdunuz ve gerekli yerlerde çağırarak uygulamanıza .txt tipinde veri aktarma özelliği eklemiş oldunuz. İlerleyen zamanlarda verilerin .csv ve .json formatlarında dışarı aktarılmasına ihtiyaç duyuldu, CsvExporter ve JsonExporter sınıflarını oluşturdunuz ve kod akışında gerekli kısımlarda koşullar ekleyerek ilgili objeleri oluşturup/çağırıp kullanarak özellikleri eklemiş oldunuz. Bir süre sonra verilerin .toml ve .xml formatlarında da dışarı aktarılmasını gerektiren bir ihtiyaç doğdu, aynı şekilde bir önceki yaptığınız gibi en başından gerekli tüm kısımlarda yeni koşullar ekleyerek uygulamanın davranışlarını kontrol ettiğiniz ilgili nesneleri oluşturup/çağırdığınız ve kullandığınız, giderek karmaşık bir hal alan yapı elde etmiş oldunuz. Tamda bu noktada, sorunun çözümü için factory method kullanmak oldukça yararlı olacaktır.
Factory method SOLID prensiplerinden open/open principle (gelişime açık değişime kapalı prensibi) içinde güzel bir uygulama yöntemidir. Creator sınıfının sağladığı ortak arayüz sayesinde ileride uygulama geliştirilmek ve yeni bir tür eklenmek istendiğinde(Concrete factory) bunu belirli standartlar ve kurallar çerçevesinde yapmayı zorunlu tutacaktır, diğer taraftan single responsibility ilkesinede oldukça uygun geliştirme yapılabilmesine olanak sağlamaktadır. Küçük bir örnek üzerinden factory methodu uygulayacak olursak;
from abc import ABC, abstractclassmethod
class Factory(ABC):
@abstractclassmethod
def produce(self):
# factory method
pass
def run_operations(self):
"""merged business logic for test operations"""
car = self.produce()
print(f"test setup applied to {car.__str__}")
print(car.move())
class ElectricCarFactory(Factory):
def produce(self) -> Car:
return ElectricCar()
class GasolineCarFactory(Factory):
def produce(self) -> Car:
return GasolineCar()
class Car(ABC):
# product
@abstractclassmethod
def move(self):
pass
class ElectricCar(Car):
def move(self):
return "i'm moving with electric power"
class GasolineCar(Car):
def move(self):
return "i'm moving with gasoline power"
class CarFactory(Factory):
def __init__(self, car:Car) -> None:
self.car = car
def produce(self):
return self.car()
def client_code(factory:Factory):
# client
factory.run_operations()
if __name__ == '__main__':
client_code(ElectricCarFactory())
client_code(GasolineCarFactory())
-----------------------------------------------------------------------
Output:
test setup applied to <method-wrapper '__str__' of ElectricCar object at 0x102964fa0>
i'm moving with electric power
test setup applied to <method-wrapper '__str__' of GasolineCar object at 0x102964fa0>
i'm moving with gasoline power
Factory method tasarım kalıbıda tüm tasarım kalıpları gibi bir takım sınırlılıklara sahiptir, oluşturulacak tüm ürünler (ElectricCar, GasolineCar) aynı ortak interface/class’ı (Car) kullanmak zorundadırlar. Çünkü ConcreteFactory sınıflarındaki factory metodları (produce) bu interface veya sınıf tipinde bir objeyi geri döndürmek zorundadır. Diğer taraftan ihtiyaç olmadığı bir senaryoda(örneğin gelecekte yeni bir ortak özelliğin eklenmesinin çok düşük ihtimal olduğu) factory method tasarım kalıbının uygulanması yeni factory classlar ve methodlar, interfaceler gibi yapıların koda eklenmesini gerektireceğinden, kodun basitliği azalacak ve karmaşası artacaktır.
Sources:
Be First to Comment