תבנית 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()) # מכונית: Ford
print(truck.info()) # משאית: 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)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםהפרמטר selfמתודותמאפייניםשיטת הבנאי (__init__)חזרה: מחשבון פשוט5פולימורפיזם
בחינה מחדש של דריסת מתודותטיפוסיות ברווזמחלקות ומתודות אבסטרקטיותעיצוב ממשקיםסיכום – מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה לעומת הורשהMixinsמתודות סטטיות ומתודות מחלקהדקורטורים למחלקותמנהלי הקשרתרגלו בעצמכם: קומפיילר Python אונליין