Padrão Factory
Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 46 de 64.
O Padrão Factory cria objetos sem especificar sua classe exata. Em vez de chamar construtores diretamente, você usa um método de fábrica que decide qual classe instanciar.
Aqui estão classes de produtos simples:
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}"Crie uma classe factory para produzir estes objetos:
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}")Use a factory em vez de chamar construtores diretamente:
factory = VehicleFactory()
my_car = factory.create_vehicle("car", "Toyota")
my_bike = factory.create_vehicle("bike", "Honda")
print(my_car.info()) # Carro: Toyota
print(my_bike.info()) # Moto: HondaTorne a fábrica mais flexível usando *args:
class FlexibleFactory:
def create_vehicle(self, vehicle_type, *args):
if vehicle_type == "car":
return Car(args[0]) # Apenas marca
elif vehicle_type == "truck":
return Truck(args[0], args[1]) # Marca e capacidade
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)"Use a fábrica flexível:
flexible = FlexibleFactory()
car = flexible.create_vehicle("car", "Ford")
truck = flexible.create_vehicle("truck", "Volvo", "20")
print(car.info()) # Carro: Ford
print(truck.info()) # Caminhão: Volvo (20t)Saída:
Car: Toyota
Bike: Honda
Car: Ford
Truck: Volvo (20t)Ponto Chave: O Padrão Factory permite que você crie objetos sem conhecer sua classe exata. O método factory decide qual classe instanciar com base em parâmetros. Use *args para lidar com produtos com diferentes parâmetros de construtor. Isso torna seu código mais flexível e fácil de estender com novos tipos de produtos.
Desafio
MédioNeste desafio, você implementará um sistema de fábrica de formas usando um design orientado a objetos adequado com herança e polimorfismo.
Complete a implementação nos seguintes arquivos:
shape.py- Classe base Shapecircle.py- Implementação de Circlerectangle.py- Implementação de Rectangletriangle.py- Implementação de Triangleshapefactory.py- Classe Factory para criar formas
Cada arquivo contém comentários TODO detalhados para guiar sua implementação. Siga estes comentários cuidadosamente para garantir que seu código atenda a todos os requisitos.
Folha de consulta
O Factory Pattern (Padrão de Fábrica) cria objetos sem especificar sua classe exata. Em vez de chamar construtores diretamente, você usa um método de fábrica que decide qual classe instanciar.
Implementação básica de fábrica:
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}")
# Uso
factory = VehicleFactory()
my_car = factory.create_vehicle("car", "Toyota")
my_bike = factory.create_vehicle("bike", "Honda")Fábrica flexível usando *args para diferentes parâmetros de construtor:
class FlexibleFactory:
def create_vehicle(self, vehicle_type, *args):
if vehicle_type == "car":
return Car(args[0]) # Apenas marca
elif vehicle_type == "truck":
return Truck(args[0], args[1]) # Marca e capacidade
else:
raise ValueError(f"Unknown type: {vehicle_type}")
# Uso
flexible = FlexibleFactory()
car = flexible.create_vehicle("car", "Ford")
truck = flexible.create_vehicle("truck", "Volvo", "20")Principais benefícios: O Factory Pattern torna o código mais flexível e fácil de estender com novos tipos de produtos sem modificar o código do cliente existente.
Experimente você mesmo
from shapefactory import ShapeFactory
from shape import Shape
from circle import Circle
from rectangle import Rectangle
from triangle import Triangle
import sys
# Executor de casos de teste
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)
# Obtém objetos de método para comparar implementações
circle_area = Circle.area
rectangle_area = Rectangle.area
triangle_area = Triangle.area
circle_perimeter = Circle.perimeter
rectangle_perimeter = Rectangle.perimeter
triangle_perimeter = Triangle.perimeter
# Verifica se todas as implementações são únicas
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")Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosO Parâmetro selfMétodosAtributosMétodo Construtor (__init__)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Função super()Sobrescrita de MétodoHerança MúltiplaOrdem de Resolução de MétodosRecapitulação - Hierarquia de Funcionários7Métodos Especiais
Introdução aos Métodos MágicosSobrecarga de OperadoresMétodos Mágicos de ContêinerRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução a Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy2Decoradores
Introdução aos DecoradoresDecorador de PropriedadeDecorador de Método EstáticoDecorador de Método de Classe5Polimorfismo
Sobrescrita de Método RevisitadaDuck TypingClasses e Métodos AbstratosDesign de InterfacesRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição vs HerançaMixinsMétodos Estáticos e de ClasseDecoradores de ClasseGerenciadores de Contexto11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Propriedades de Classe
Variáveis de Instância vs de ClasseDecoradores de PropriedadeAtributos PrivadosRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Membros Públicos, Protegidos e PrivadosModificadores de AcessoOcultação de InformaçãoProperty Decorators AvançadosRecapitulação - Sistema de Registro de Alunos12Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário