Factory Method
Definição
O Factory Method define uma interface para criação de objetos, delegando às subclasses a responsabilidade de decidir qual instância criar.
Em vez de criar objetos diretamente com new
(ou o
construtor), o padrão delega essa criação a um método especializado — o
Factory Method.
Por que é importante
Esse padrão promove o princípio aberto/fechado, permitindo adicionar novos tipos de objetos sem modificar o código que os utiliza.
Também ajuda a encapsular a lógica de criação e permite que subclasses ou componentes decidam dinamicamente qual objeto criar, mantendo flexibilidade e baixo acoplamento.
Antes de aplicar o Factory Method (Python)
Veja um exemplo comum onde a lógica de criação está misturada com a lógica de uso. Esse código funciona, mas viola o princípio aberto/fechado e acopla o sistema às implementações concretas:
# Implementações concretas
class EmailNotificacao:
def enviar(self, mensagem):
print(f"Enviando E-mail: {mensagem}")
class SMSNotificacao:
def enviar(self, mensagem):
print(f"Enviando SMS: {mensagem}")
# Código acoplado à criação dos objetos
def notificar(mensagem, canal):
if canal == "email":
notificacao = EmailNotificacao()
elif canal == "sms":
notificacao = SMSNotificacao()
else:
raise ValueError("Canal inválido")
notificacao.enviar(mensagem)
Esse modelo exige que o código principal conheça todas as classes concretas e seja modificado sempre que surgir um novo tipo de notificação. Isso dificulta a extensão do sistema e fere a ideia de encapsulamento da criação.
Exemplo prático com Factory Method (Python)
Vamos supor um sistema de notificações que pode enviar mensagens por e-mail ou SMS. Em vez de instanciar as notificações diretamente, usamos um método de fábrica para decidir qual objeto criar:
from abc import ABC, abstractmethod
# Produto base
class Notificacao(ABC):
@abstractmethod
def enviar(self, mensagem):
pass
# Implementações concretas
class EmailNotificacao(Notificacao):
def enviar(self, mensagem):
print(f"Enviando E-mail: {mensagem}")
class SMSNotificacao(Notificacao):
def enviar(self, mensagem):
print(f"Enviando SMS: {mensagem}")
# Criador base
class Notificador(ABC):
# Este é o Factory Method — ele será sobrescrito para criar a notificação certa
@abstractmethod
def criar_notificacao(self) -> Notificacao:
pass
def notificar(self, mensagem):
notificacao = self.criar_notificacao()
notificacao.enviar(mensagem)
# Fábricas concretas
class NotificadorEmail(Notificador):
def criar_notificacao(self):
return EmailNotificacao()
class NotificadorSMS(Notificador):
def criar_notificacao(self):
return SMSNotificacao()
Agora, o código principal não precisa mais conhecer as implementações concretas diretamente. Ele apenas usa a abstração:
notificador = NotificadorEmail()
notificador.notificar("Bem-vindo!")
notificador = NotificadorSMS()
notificador.notificar("Seu código é 1234")
Com isso, podemos adicionar novos tipos de notificação no futuro sem
modificar o código existente, apenas criando uma nova subclasse de
Notificador
. Esse padrão também facilita testes e manutenção,
já que é possível substituir facilmente as fábricas por versões mockadas
ou alternativas sem alterar o código de uso.