工厂模式
本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 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:Circle 的实现rectangle.py:Rectangle 的实现triangle.py:Triangle 的实现shapefactory.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")这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Python 在线编译器