Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط Factory

جزء من قسم Object Oriented Programming في رحلة Python على Coddy — الدرس 46 من 64.

يقوم نمط المصنع (Factory Pattern) بإنشاء الكائنات دون تحديد فئتها (class) الدقيقة. فبدلاً من استدعاء المنشئات (constructors) مباشرة، تستخدم طريقة مصنع (factory method) تقرر أي فئة سيتم إنشاؤها (instantiate).

إليك فئات منتجات بسيطة:

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}"

أنشئ فئة مصنع لإنتاج هذه الكائنات:

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}")

استخدم المصنع بدلاً من استدعاء المنشئات (constructors) مباشرةً:

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

print(my_car.info())   # سيارة: Toyota
print(my_bike.info())  # دراجة: Honda

اجعل المصنع أكثر مرونة باستخدام *args:

class FlexibleFactory:
    def create_vehicle(self, vehicle_type, *args):
        if vehicle_type == "car":
            return Car(args[0])  # Just brand
        elif vehicle_type == "truck":
            return Truck(args[0], args[1])  # Brand and capacity
        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)"

استخدم المصنع المرن:

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

print(car.info())    # سيارة: Ford
print(truck.info())  # شاحنة: Volvo (20t)

المخرجات:

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

نقطة رئيسية: يتيح لك نمط المصنع (Factory Pattern) إنشاء كائنات دون معرفة فئتها (class) المحددة. تحدد طريقة المصنع (factory method) الفئة التي سيتم إنشاؤها بناءً على المعاملات (parameters). استخدم *args للتعامل مع المنتجات التي تحتوي على معاملات منشئ (constructor parameters) مختلفة. هذا يجعل الكود الخاص بك أكثر مرونة وأسهل في التوسع مع أنواع منتجات جديدة.

challenge icon

التحدي

متوسط

في هذا التحدي، ستقوم بتنفيذ نظام مصنع أشكال باستخدام تصميم كائني التوجه سليم مع الوراثة وتعدد الأشكال.

أكمل التنفيذ في الملفات التالية:

  • shape.py - فئة Shape الأساسية
  • circle.py - تنفيذ Circle
  • rectangle.py - تنفيذ Rectangle
  • triangle.py - تنفيذ Triangle
  • shapefactory.py - فئة Factory لإنشاء الأشكال

يحتوي كل ملف على تعليقات TODO مفصلة لتوجيهك في التنفيذ. اتبع هذه التعليقات بعناية للتأكد من أن الكود الخاص بك يلبي جميع المتطلبات.

ورقة مرجعية

يقوم نمط المصنع (Factory Pattern) بإنشاء الكائنات دون تحديد فئتها (class) الدقيقة. فبدلاً من استدعاء المنشئات (constructors) مباشرة، تستخدم طريقة مصنع (factory method) تقرر أي فئة سيتم إنشاؤها.

تنفيذ أساسي للمصنع:

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}")

# الاستخدام
factory = VehicleFactory()
my_car = factory.create_vehicle("car", "Toyota")
my_bike = factory.create_vehicle("bike", "Honda")

مصنع مرن يستخدم *args لمعاملات منشئ مختلفة:

class FlexibleFactory:
    def create_vehicle(self, vehicle_type, *args):
        if vehicle_type == "car":
            return Car(args[0])  # العلامة التجارية فقط
        elif vehicle_type == "truck":
            return Truck(args[0], args[1])  # العلامة التجارية والسعة
        else:
            raise ValueError(f"Unknown type: {vehicle_type}")

# الاستخدام
flexible = FlexibleFactory()
car = flexible.create_vehicle("car", "Ford")
truck = flexible.create_vehicle("truck", "Volvo", "20")

الفوائد الرئيسية: يجعل نمط المصنع الكود أكثر مرونة وأسهل في التوسع مع أنواع منتجات جديدة دون تعديل كود العميل الحالي.

جرّب بنفسك

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

# منفذ حالات الاختبار
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)
    
    # الحصول على كائنات الدوال لمقارنة التنفيذات
    circle_area = Circle.area
    rectangle_area = Rectangle.area
    triangle_area = Triangle.area
    
    circle_perimeter = Circle.perimeter
    rectangle_perimeter = Rectangle.perimeter
    triangle_perimeter = Triangle.perimeter
    
    # التحقق مما إذا كانت جميع التنفيذات فريدة
    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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming