Implementando o Padrão de Projeto Prototype em Java

Entendendo o Padrão Prototype

O padrão de projeto Prototype é um padrão criacional que permite a replicação de objetos existentes sem que o código dependa de suas classes específicas. Em termos práticos, este padrão fundamenta-se no conceito de clonagem. Em vez de instanciar um novo objeto do zero e configurar todos os seus atributos manualmente, utilizamos uma instância existente (o protótipo) como base para gerar novas cópias.

Ao lidar com clonagem em linguagens como Java, é crucial distinguir entre dois conceitos fundamentais:

  • Shallow Copy (Cópia Rasa): Copia os valores dos campos primitivos. No caso de campos que são referências a objetos, apenas o endereço de memória é copiado, o que significa que o objeto original e o clonado compartilharão a mesma instância do objeto interno.
  • Deep Copy (Cópia Profunda): Além de copiar os primitivos, cria novas instâncias para todos os objetos referenciados internamente, garantindo independência total entre o protótipo e o clone.

Implementação Prática

Abaixo, apresentamos uma implementação em Java utilizando a interface Cloneable para demonstrar a técnica de Deep Copy.

1. Definição da Classe Dependente

Primeiro, definimos uma classe que representa uma dependência interna, como o histórico profissional de um usuário.

public class HistoricoProfissional implements Cloneable {
    private String periodo;
    private String empresa;

    public HistoricoProfissional(String periodo, String empresa) {
        this.periodo = periodo;
        this.empresa = empresa;
    }

    // Getters e Setters omitidos

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // Implementação padrão de cópia rasa para esta classe simples
        return super.clone();
    }

    @Override
    public String toString() {
        return "HistoricoProfissional{periodo='" + periodo + "', empresa='" + empresa + "'}";
    }
}

2. Implementação do Protótipo com Deep Copy

A classe principal implementa a lógica de clonagem profunda para garantir que o objeto interno também seja duplicado.

public class PerfilUsuario implements Cloneable {
    private String nome;
    private int idade;
    private HistoricoProfissional historico;

    public PerfilUsuario(String nome, int idade, HistoricoProfissional historico) {
        this.nome = nome;
        this.idade = idade;
        this.historico = historico;
    }

    // Getters e Setters omitidos

    @Override
    public PerfilUsuario clone() throws CloneNotSupportedException {
        // Primeiro, realiza a cópia rasa da classe principal
        PerfilUsuario novoPerfil = (PerfilUsuario) super.clone();
        
        // Em seguida, realiza a clonagem manual do objeto interno (Deep Copy)
        if (this.historico != null) {
            novoPerfil.historico = (HistoricoProfissional) this.historico.clone();
        }
        
        return novoPerfil;
    }

    @Override
    public String toString() {
        return "PerfilUsuario{nome='" + nome + "', idade=" + idade + ", historico=" + historico + "}";
    }
}

3. Execução e Validação

O código a seguir demonstra como o Prototype se comporta e valida se as instâncias são realmente independentes.

public class ExemploPrototype {
    public static void main(String[] args) throws CloneNotSupportedException {
        HistoricoProfissional exp = new HistoricoProfissional("2020-2023", "Tech Corp");
        PerfilUsuario original = new PerfilUsuario("Carlos Silva", 30, exp);

        // Criando uma cópia via Prototype
        PerfilUsuario clone = original.clone();

        // Modificando o clone
        clone.setNome("Carlos Souza");
        
        System.out.println("Original: " + original);
        System.out.println("Clone: " + clone);

        // Verificação de independência de memória
        boolean mesmoObjetoInterno = (original.getHistorico() == clone.getHistorico());
        System.out.println("Mesma referência de histórico? " + mesmoObjetoInterno); 
        // Resultado esperado: false (Deep Copy funcional)
    }
}

Considerações sobre o Uso

Em Java, a implementação do Prototype através da interface Cloneable e do método clone() é o caminho nativo, porém requer atenção redobrada. Para estruturas de objetos complexas e profundamente aninhadas, o desenvolvedor deve garantir que cada nível da hierarquia suporte a clonagem de forma correta, evitando efeitos colaterais onde alterações em um objeto clonado afetam o original inesperadamente.

Tags: java design patterns Prototype Pattern Object Oriented Programming Software Architecture

Publicado em 6-8 00:30 por Thomas