O Prototype é um padrão de projeto criacional que permite copiar objetos existentes sem fazer seu código ficar dependente de suas classes. O padrão delega o processo de clonagem para os próprios objetos que estão sendo clonados.
- Quando seu código não deve depender de classes concretas de objetos que você precisa copiar
- Quando você precisa reduzir o número de subclasses que só diferem na forma que inicializam seus objetos
- Quando você precisa criar cópias de objetos sem conhecer seus tipos específicos
- Quando você precisa criar objetos similares evitando repetição de código de inicialização
from abc import ABC, abstractmethod
import copy
# Interface do protótipo
class Prototype(ABC):
@abstractmethod
def clone(self):
pass
# Protótipo concreto
class Documento(Prototype):
def __init__(self, nome: str, conteudo: list):
self.nome = nome
self.conteudo = conteudo
def clone(self):
# Usando deep copy para garantir que todos os objetos aninhados também sejam copiados
return copy.deepcopy(self)
def __str__(self):
return f"Documento: {self.nome}, Conteúdo: {self.conteudo}"
# Protótipo concreto mais complexo
class DocumentoComFormato(Documento):
def __init__(self, nome: str, conteudo: list, formato: str):
super().__init__(nome, conteudo)
self.formato = formato
def clone(self):
return copy.deepcopy(self)
def __str__(self):
return f"Documento: {self.nome}, Conteúdo: {self.conteudo}, Formato: {self.formato}"
# Gerenciador de protótipos
class GerenciadorDocumentos:
def __init__(self):
self._documentos = {}
def adicionar_documento(self, chave: str, documento: Prototype):
self._documentos[chave] = documento
def obter_documento(self, chave: str) -> Prototype:
doc = self._documentos.get(chave)
return doc.clone() if doc else None
# Exemplo de uso
def main():
# Criando gerenciador
gerenciador = GerenciadorDocumentos()
# Criando e registrando protótipos
doc_simples = Documento("Doc1", ["página 1", "página 2"])
doc_formatado = DocumentoComFormato("Doc2", ["seção 1", "seção 2"], "PDF")
gerenciador.adicionar_documento("simples", doc_simples)
gerenciador.adicionar_documento("formatado", doc_formatado)
# Clonando documentos
doc_clone1 = gerenciador.obter_documento("simples")
doc_clone2 = gerenciador.obter_documento("formatado")
# Modificando clones
doc_clone1.conteudo.append("página 3")
doc_clone2.formato = "DOCX"
# Verificando que os originais não foram alterados
print(doc_simples) # Original mantido
print(doc_clone1) # Clone modificado
print(doc_formatado) # Original mantido
print(doc_clone2) # Clone modificado
if __name__ == "__main__":
main()- Permite clonar objetos sem acoplamento a suas classes concretas
- Reduz código duplicado de inicialização
- Cria objetos complexos mais convenientemente
- Fornece uma alternativa à herança para lidar com configurações pré-definidas
- Clonar objetos complexos com referências circulares pode ser complicado
- A implementação do método de clonagem pode ser desafiadora em algumas situações
- Pode haver problemas com a cópia profunda vs. superficial dos objetos
- Decida entre implementar clone profundo ou superficial baseado nas necessidades
- Considere usar um registro de protótipos para gerenciar os protótipos disponíveis
- Implemente a clonagem cuidadosamente para objetos que contêm referências a outros objetos
- Use o método clone() em vez de criar novas instâncias diretamente