Menu
Coddy logo textTech

Factory Kalıbı

Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 46 / 64.

Factory Deseni, nesneleri tam sınıflarını belirtmeden oluşturur. Yapıcıları (constructors) doğrudan çağırmak yerine, hangi sınıfın örnekleneceğine karar veren bir fabrika yöntemi (factory method) kullanırsınız.

İşte basit ürün sınıfları:

class Car:
    def __init__(self, brand):
        self.brand = brand
        self.type = "Car"
    
    def info(self):
        return f"{self.type}: {self.brand}"

class Bike:
    def __init__(self, brand):
        self.brand = brand
        self.type = "Bike"
    
    def info(self):
        return f"{self.type}: {self.brand}"

Bu nesneleri üretmek için bir fabrika sınıfı oluşturun:

class VehicleFactory:
    def create_vehicle(self, vehicle_type, brand):
        if vehicle_type == "car":
            return Car(brand)
        elif vehicle_type == "bike":
            return Bike(brand)
        else:
            raise ValueError(f"Unknown type: {vehicle_type}")

Yapıcıları doğrudan çağırmak yerine fabrikayı kullanın:

factory = VehicleFactory()
my_car = factory.create_vehicle("car", "Toyota")
my_bike = factory.create_vehicle("bike", "Honda")

print(my_car.info())   # Araba: Toyota
print(my_bike.info())  # Bisiklet: Honda

Fabrikayı *args kullanarak daha esnek hale getirin:

class FlexibleFactory:
    def create_vehicle(self, vehicle_type, *args):
        if vehicle_type == "car":
            return Car(args[0])  # Sadece marka
        elif vehicle_type == "truck":
            return Truck(args[0], args[1])  # Marka ve kapasite
        else:
            raise ValueError(f"Unknown type: {vehicle_type}")

class Truck:
    def __init__(self, brand, capacity):
        self.brand = brand
        self.capacity = capacity
        self.type = "Truck"
    
    def info(self):
        return f"{self.type}: {self.brand} ({self.capacity}t)"

Esnek fabrikayı kullanın:

flexible = FlexibleFactory()
car = flexible.create_vehicle("car", "Ford")
truck = flexible.create_vehicle("truck", "Volvo", "20")

print(car.info())    # Araba: Ford
print(truck.info())  # Kamyon: Volvo (20t)

Çıktı:

Car: Toyota
Bike: Honda
Car: Ford
Truck: Volvo (20t)

Anahtar Nokta: Fabrika Deseni (Factory Pattern), tam sınıflarını bilmeden nesneler oluşturmanıza olanak tanır. Fabrika yöntemi, parametrelere bağlı olarak hangi sınıfın örnekleneceğine karar verir. Farklı yapıcı (constructor) parametrelerine sahip ürünleri işlemek için *args kullanın. Bu, kodunuzu daha esnek hale getirir ve yeni ürün türleriyle genişletilmesini kolaylaştırır.

challenge icon

Görev

Orta

Bu meydan okumada, kalıtım ve polimorfizm kullanarak uygun bir nesne yönelimli tasarıma sahip bir şekil fabrikası (shape factory) sistemi uygulayacaksınız.

Aşağıdaki dosyalardaki uygulamaları tamamlayın:

  • shape.py - Temel Shape sınıfı
  • circle.py - Circle uygulaması
  • rectangle.py - Rectangle uygulaması
  • triangle.py - Triangle uygulaması
  • shapefactory.py - Şekil oluşturmak için Fabrika (Factory) sınıfı

Her dosya, uygulamanıza rehberlik edecek ayrıntılı TODO yorumları içerir. Kodunuzun tüm gereksinimleri karşıladığından emin olmak için bu yorumları dikkatlice takip edin.

Kopya kağıdı

Factory Deseni, nesneleri tam sınıflarını belirtmeden oluşturur. Doğrudan yapıcıları (constructors) çağırmak yerine, hangi sınıfın örnekleneceğine karar veren bir fabrika yöntemi kullanırsınız.

Temel fabrika uygulaması:

class VehicleFactory:
    def create_vehicle(self, vehicle_type, brand):
        if vehicle_type == "car":
            return Car(brand)
        elif vehicle_type == "bike":
            return Bike(brand)
        else:
            raise ValueError(f"Unknown type: {vehicle_type}")

# Kullanım
factory = VehicleFactory()
my_car = factory.create_vehicle("car", "Toyota")
my_bike = factory.create_vehicle("bike", "Honda")

Farklı yapıcı parametreleri için *args kullanan esnek fabrika:

class FlexibleFactory:
    def create_vehicle(self, vehicle_type, *args):
        if vehicle_type == "car":
            return Car(args[0])  # Sadece marka
        elif vehicle_type == "truck":
            return Truck(args[0], args[1])  # Marka ve kapasite
        else:
            raise ValueError(f"Unknown type: {vehicle_type}")

# Kullanım
flexible = FlexibleFactory()
car = flexible.create_vehicle("car", "Ford")
truck = flexible.create_vehicle("truck", "Volvo", "20")

Temel avantajlar: Factory Deseni, mevcut istemci kodunu değiştirmeden kodu daha esnek hale getirir ve yeni ürün türleriyle genişletilmesini kolaylaştırır.

Kendin dene

from shapefactory import ShapeFactory
from shape import Shape
from circle import Circle
from rectangle import Rectangle
from triangle import Triangle
import sys

# Test durumu yürütücüsü
test_case = input()

factory = ShapeFactory()

if test_case == "circle_area":
    circle = factory.create_shape("circle", 5)
    print(f"{circle.area():.2f}")

elif test_case == "rectangle_perimeter":
    rectangle = factory.create_shape("rectangle", 4, 6)
    print(f"{rectangle.perimeter()}")

elif test_case == "triangle_perimeter":
    triangle = factory.create_shape("triangle", 3, 4, 5)
    print(f"{triangle.perimeter()}")

elif test_case == "invalid_shape":
    try:
        factory.create_shape("hexagon", 6)
        print("No exception raised")
    except ValueError as e:
        print(str(e))

elif test_case == "case_insensitive":
    circle = factory.create_shape("CiRcLe", 3)
    print(f"{circle.area():.2f}")

elif test_case == "shape_inheritance":
    shapes = [
        factory.create_shape("circle", 2),
        factory.create_shape("rectangle", 2, 3),
        factory.create_shape("triangle", 3, 4, 5)
    ]
    all_shapes = all(isinstance(shape, Shape) for shape in shapes)
    print(all_shapes)

elif test_case == "zero_radius_circle":
    circle = factory.create_shape("circle", 0)
    print(f"{circle.area():.2f} {circle.perimeter():.2f}")

elif test_case == "negative_dimensions":
    rectangle = factory.create_shape("rectangle", -2, -3)
    print(f"{rectangle.area()}")

elif test_case == "large_values":
    circle = factory.create_shape("circle", 1000000)
    print(f"{circle.area():.2e}")

elif test_case == "polymorphism_test":
    shapes = [
        factory.create_shape("circle", 2),
        factory.create_shape("rectangle", 3, 4),
        factory.create_shape("triangle", 3, 4, 5)
    ]
    area_sum = sum(shape.area() for shape in shapes)
    perimeter_sum = sum(shape.perimeter() for shape in shapes)
    print(f"Area sum: {area_sum:.2f}, Perimeter sum: {perimeter_sum:.2f}")

elif test_case == "triangle_area":
    triangle = factory.create_shape("triangle", 3, 4, 5)
    print(f"{triangle.area():.2f}")

elif test_case == "method_override":
    circle = factory.create_shape("circle", 2)
    rectangle = factory.create_shape("rectangle", 3, 4)
    triangle = factory.create_shape("triangle", 3, 4, 5)
    
    # Uygulamaları karşılaştırmak için metot nesnelerini al
    circle_area = Circle.area
    rectangle_area = Rectangle.area
    triangle_area = Triangle.area
    
    circle_perimeter = Circle.perimeter
    rectangle_perimeter = Rectangle.perimeter
    triangle_perimeter = Triangle.perimeter
    
    # Tüm uygulamaların benzersiz olup olmadığını kontrol et
    unique_areas = len({circle_area, rectangle_area, triangle_area}) == 3
    unique_perimeters = len({circle_perimeter, rectangle_perimeter, triangle_perimeter}) == 3
    
    if unique_areas and unique_perimeters:
        print("All shapes correctly override methods")
    else:
        print("Some shapes share method implementations")
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler