نمط Factory
جزء من قسم البرمجة كائنية التوجه في رحلة Python على Coddy. الدرس 46 من 64.
ينشئ نمط المصنع كائنات دون تحديد فئتها الدقيقة. بدلًا من استدعاء المُنشئات مباشرةً، تستخدم أسلوب مصنع يحدد الفئة التي سيتم إنشاء مثيل منها.
إليك فئات منتجات بسيطة:
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}")يُسمّى الكود الذي يحتاج إلى الكائنات كود العميل. فهو يطلبها من المصنع بدلًا من استدعاء المُنشئات مباشرةً:
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]) # العلامة التجارية فقط
elif vehicle_type == "truck":
return Truck(args[0], args[1]) # العلامة التجارية والحمولة
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()) # Car: Ford
print(truck.info()) # Truck: Volvo (20t)المخرجات:
Car: Toyota
Bike: Honda
Car: Ford
Truck: Volvo (20t)النقطة الأساسية: يتيح لك نمط المصنع إنشاء كائنات دون معرفة فئتها الدقيقة. تحدد طريقة المصنع الفئة التي سيتم إنشاء مثيل لها بناءً على المعلمات. استخدم *args للتعامل مع المنتجات ذات معلمات المُنشئ المختلفة. هذا يجعل التعليمات البرمجية أكثر مرونة وأسهل في التوسيع بإضافة أنواع جديدة من المنتجات.
التحدي
متوسطفي هذا التحدي، ستنفّذ نظامًا لمصنع الأشكال باستخدام تصميم سليم موجّه للكائنات مع الوراثة وتعدد الأشكال.
أكمل التنفيذ في الملفات التالية:
shape.py- الفئة الأساسية Shapecircle.py- تنفيذ Circlerectangle.py- تنفيذ Rectangletriangle.py- تنفيذ Triangleshapefactory.py- فئة المصنع لإنشاء الأشكال
يحتوي كل ملف على تعليقات TODO مفصّلة لإرشادك خلال التنفيذ. اتبع هذه التعليقات بعناية لضمان استيفاء التعليمات البرمجية لجميع المتطلبات.
جرّب بنفسك
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")يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsمعامل selfMethodsAttributesدالة البناء (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكالتدرّب بنفسك: مترجم Python عبر الإنترنت