<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Breno Baudson</title>
    <description>The latest articles on DEV Community by Breno Baudson (@breno_baudson).</description>
    <link>https://dev.to/breno_baudson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3027828%2Fc69b5831-4b11-4ff8-820d-c3c5a24a46eb.jpg</url>
      <title>DEV Community: Breno Baudson</title>
      <link>https://dev.to/breno_baudson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/breno_baudson"/>
    <language>en</language>
    <item>
      <title>Singleton de forma simples</title>
      <dc:creator>Breno Baudson</dc:creator>
      <pubDate>Wed, 30 Apr 2025 14:38:05 +0000</pubDate>
      <link>https://dev.to/breno_baudson/singleton-kf2</link>
      <guid>https://dev.to/breno_baudson/singleton-kf2</guid>
      <description>&lt;p&gt;Singleton é um padrão criacional que garante uma única instância para um objeto, além de fornecer um ponto de acesso global para essa instância. Em outras palavras, o objeto será criado apenas &lt;strong&gt;uma&lt;/strong&gt; vez em todo o processo.&lt;/p&gt;

&lt;p&gt;Imagine que você está construindo um sistema para uma escola. Este sistema deverá viabilizar dentre outras funcionalidades, a matricula de alunos. Durante o processo de cadastro é necessário indicar o diretor vigente, que é único. Dentre várias possibilidades, o padrão &lt;em&gt;Singleton&lt;/em&gt; tem o objetivo de solucionar este tipo de problema.&lt;/p&gt;

&lt;p&gt;Vamos implementar um código na prática sem um padrão bem definido e com o Singleton. Acompanhe:&lt;/p&gt;

&lt;h2&gt;
  
  
  Sem Singleton
&lt;/h2&gt;

&lt;p&gt;Classe Diretor com construtor publico (todos podem criar uma nova instância de diretor)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
public class Diretor {

    private String nome;
    private String sobrenome;

    public Diretor(String nome, String sobrenome) {
        this.nome = nome;
        this.sobrenome = sobrenome;
    }    
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sempre que diretor for instânciado, um novo objeto será criado (new Diretor)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {

        Diretor diretor = new Diretor("josé", "Silva");
        System.out.println("Nome:" + diretor.getNome());
        System.out.println(diretor);

        Diretor outroDiretor = new Diretor("josé", "Silva");
        System.out.println("Nome:" + outroDiretor.getNome());
        System.out.println(outroDiretor);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpiqs8wofqh2al22w9l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpiqs8wofqh2al22w9l9.png" alt="Image description" width="756" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notem que são dois objetos diferentes. Imagine que um aluno foi matriculado e o diretor foi "José", um professor foi contratado e o diretor foi "joão". Cada ponto do sistema, um novo objeto sendo criado e possibilitando trocar o valor dos atributos. Isso pode causar decisões conflitantes, bugs e resultados não esperados. Por isso há a necessidade de criar um objeto único...&lt;/p&gt;

&lt;h2&gt;
  
  
  Com Singleton
&lt;/h2&gt;

&lt;p&gt;Classe diretor criada, mas dessa vez com um construtor privado. Isso significa que apenas a classe diretor terá acesso ao próprio construtor. Ou seja, ninguém mais poderá criar um Diretor a não ser a própria classe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
public class Diretor {
    private static Diretor instance;

    private String nome;
    private String sobrenome;

    private Diretor(String nome, String sobrenome) {
       this.nome = nome;
         this.sobrenome = sobrenome;
    }

    public static Diretor getInstance(String nome, String sobrenome) {
        if (instance == null) {
            instance = new Diretor(nome, sobrenome);
        }
        return instance;
    }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora a classe cliente deverá chamar o método getInstance() ao invés de new Diretor(..). O método por sua vez, devolverá sempre a mesma instância caso ela já exista.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {

        Diretor diretor = Diretor.getInstance("joão", "Silva");
        System.out.println("Nome:" + diretor.getNome());
        System.out.println(diretor);

        Diretor outroDiretor = Diretor.getInstance("fulado", "de tal");
        System.out.println("Nome:" + outroDiretor.getNome());
        System.out.println(outroDiretor);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfgbcf85k8chlbe11y8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfgbcf85k8chlbe11y8j.png" alt="Image description" width="580" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notem que agora, o objeto retornado sempre será o mesmo, pois foi instânciado apenas uma vez.&lt;/p&gt;

&lt;p&gt;Como na maioria esmagadoras dos casos (quase me atrevo a dizer todos), esta não é a única forma de resolver este problema. Poderíamos usar, por exemplo, a injeção de dependências, deixando o código um pouco mais fácil de manter e testar. Entretanto, o intuito é avaliar este padrão em específico, como implementa-lo, quais suas vantagens e desvantagens.&lt;/p&gt;

&lt;p&gt;Existem diversos outros exemplos de implementação do padrão Singleton. Dentre os mais famosos, temos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;gerenciamento de configurações de sistemas. Exemplo: o Singleton ser a classe responsável por trocar o tema da IDE. Sempre teremos um único tema por vês e por isso o Singleton faz sentido.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;gerenciamento de instâncias de banco de dados. Exemplo: ter um Singleton responsável por abrir uma conexão e mantê-la. Disponibilizando-a para quem precisar sem precisar abrir novas conexões, economizando recursos e otimizando performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Vantagens
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Garantia de unicidade&lt;/strong&gt;: garante que haja apenas um diretor na escola.&lt;br&gt;
&lt;strong&gt;Acesso centralizado&lt;/strong&gt;: permite que qualquer parte do sistema, como professores, alunos, secretários(...) acesse facilmente as informações e os métodos do diretor.&lt;br&gt;
&lt;strong&gt;Controle de recursos&lt;/strong&gt;: se o diretor precisar gerenciar recursos limitados, como vagas em turmas ou orçamento, o Singleton garante que ele tenha uma visão centralizada e evite conflitos.&lt;br&gt;
&lt;strong&gt;Consistência&lt;/strong&gt;: garante que todos os componentes do sistema estejam trabalhando com as mesmas informações e diretrizes do diretor.&lt;/p&gt;

&lt;p&gt;Desvantagens&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsabilidade única&lt;/strong&gt;: viola o princípio da responsabilidade única pois a classe Singleton assume a responsabilidade de criar e gerenciar sua própria instância.&lt;br&gt;
&lt;strong&gt;Aumenta complexidade de testar&lt;/strong&gt;: dificulta a criação de testes unitários para as classes que dependem do diretor, pois é difícil substituir o Singleton por um "mock" ou "stub" durante os testes.&lt;br&gt;
&lt;strong&gt;Acoplamento global&lt;/strong&gt;: cria um acoplamento global entre a classe Diretor e as classes que a utilizam, tornando o código menos flexível e mais difícil de modificar.&lt;br&gt;
&lt;strong&gt;Dificuldade de escalabilidade&lt;/strong&gt;: pode dificultar a evolução do sistema, pois a dependência global do diretor pode tornar difícil a introdução de novas funcionalidades ou a modificação das existentes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entenda também
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/breno_baudson/implementando-abstract-factory-44h6"&gt;Abstract Factory&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/breno_baudson/factory-method-j44"&gt;Factory Method&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>singleton</category>
      <category>designpatterns</category>
      <category>boaspraticas</category>
      <category>orientacaoaobjetos</category>
    </item>
    <item>
      <title>Abstract Factory na prática!</title>
      <dc:creator>Breno Baudson</dc:creator>
      <pubDate>Wed, 23 Apr 2025 22:01:27 +0000</pubDate>
      <link>https://dev.to/breno_baudson/implementando-abstract-factory-44h6</link>
      <guid>https://dev.to/breno_baudson/implementando-abstract-factory-44h6</guid>
      <description>&lt;p&gt;O &lt;em&gt;Abstract Factory&lt;/em&gt; é um padrão de projeto do tipo criacional que oferece uma solução eficiente para criar uma família de objetos relacionados, sem especificar as classes concretas. Em outras palavras, ele permite criar grupos de objetos através de &lt;strong&gt;abstrações&lt;/strong&gt;/ interfaces. Tudo isso, garantindo que os objetos sejam compatíveis entre si.&lt;/p&gt;

&lt;p&gt;Imagine que você está desenvolvendo um sistema para uma escola e ela  tenha diferentes níveis de ensino, como &lt;em&gt;ensino fundamental&lt;/em&gt; e &lt;em&gt;ensino médio&lt;/em&gt;. E que, cada nível precise de um conjunto específico de objetos relacionados como, alunos, professores e materiais didáticos. Esses objetos têm características distintas dependendo do nível de ensino. Por exemplo:&lt;/p&gt;

&lt;p&gt;Alunos do fundamental podem ter atributos como "responsável legal" e alunos do ensino médio não terão este atributo.&lt;br&gt;
Professores do ensino médio podem ter especializações específicas, ao contrário do ensino fundamental.&lt;br&gt;
Materiais didáticos variam conforme o nível (livros infantis no fundamental e livros técnicos no Médio).&lt;/p&gt;

&lt;p&gt;Com o &lt;em&gt;Abstract Factory&lt;/em&gt;, podemos criar uma fábrica abstrata que terá métodos para criar as famílias dos objetos relacionados (aluno, professor e material didático). Cada implementação concreta da fábrica será responsável por criar objetos específicos para cada nível de ensino.&lt;/p&gt;

&lt;p&gt;Façamos um comparativo entre uma implementação inicial sem padrão definido e uma com o padrão &lt;em&gt;Abstract Factory&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sem padrão definido
&lt;/h2&gt;

&lt;p&gt;Criei uma classe para Pessoa. De forma que eu reaproveite código entre Aluno e Professor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Pessoa {
    private String nome;
    private String sobrenome;
    private String email;

    public Pessoa(String nome, String sobrenome, String email) {
        this.nome = nome;
        this.sobrenome = sobrenome;
        this.email = email;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criei uma classe para Aluno, que terá o atributo responsavelLegal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
@Setter
public class Aluno extends Pessoa {

    private Pessoa responsavelLegal;

    public Aluno(String nome, String sobrenome, String email) {
        super(nome, sobrenome, email);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criei a classe Professor que terá mais dois atributos adicionais&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
@Setter
public class Professor extends Pessoa {

    private String disciplina;
    private String especializacao;

    public Professor(String nome, String sobrenome, String email) {
        super(nome, sobrenome, email);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criei uma classe para MaterialDidatico&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Getter
@Setter
@AllArgsConstructor
public class MaterialDidatico {
    private String livro;
    private BigDecimal preco;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desta forma, quando a classe &lt;em&gt;cliente&lt;/em&gt; precisar matricular um aluno, deverá conhecer a implementação de cada objeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class EscolaService {

    public void matricularAluno(){
        Pessoa responsavel = new Pessoa("responsavel", "legal", "email2");

        Aluno aluno = new Aluno("fulano","silva", "email1");
        aluno.setResponsavelLegal(responsavel);

        Professor professor = new Professor("professor", "silva", "email3");
        professor.setDisciplina("Geral");

        MaterialDidatico materialDidatico = new MaterialDidatico("livro I", new BigDecimal(100));

        ///restante da implementação

    }    
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta prática, embora simples, pode tornar a classe cliente extremamente grande, complexa, acoplada, difícil de manter, entender e escalar.&lt;br&gt;
Por outro lado, a implementação do Abstract Factory nesse exemplo pode resolver todos estes problemas. Acompanhe...:&lt;/p&gt;
&lt;h2&gt;
  
  
  Com Abstract Factory
&lt;/h2&gt;

&lt;p&gt;Criei uma interface para criar os objetos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface EnsinoFactory {

    Aluno criarAluno(String nome, String sobrenome, String email, String responsavel);

    Professor criarProfessor(String nome, String sobrenome, String email, String disciplina, String especializacao);

    MaterialDidatico criarMaterialDidatico();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E uma classe concreta para o ensino fundamental. Aqui, implementei uma regra exigindo que o responsável legal seja populado para o Aluno e ignorei a especialização do professor. Por outro lado, o material didático já possui suas próprias regras, desprezando parâmetros de entrada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class EnsinoFundamentalFactory implements EnsinoFactory {

    @Override
    public Aluno criarAluno(String nome, String sobrenome, String email, String responsavel) {
        if (responsavel == null || responsavel.isEmpty()) {
            throw new IllegalArgumentException("Responsável não pode ser nulo ou vazio");
        }
        return new Aluno(nome, sobrenome, email, responsavel);
    }

    @Override
    public Professor criarProfessor(String nome, String sobrenome, String email, String disciplina, String especializacao) {
        return new Professor(nome, sobrenome, email);
    }

    @Override
    public MaterialDidatico criarMaterialDidatico() {
        return new MaterialDidatico("Livro Infantil I", new BigDecimal("100.00"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O mesmo sobre a classe concreta do ensino médio. Aqui garanti que a especialização do professor seja informada. Desconsiderei o responsável do aluno e já criei o material didático com suas especificidades.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public class EnsinoMedioFactory implements EnsinoFactory {

    @Override
    public Aluno criarAluno(String nome, String sobrenome, String email, String responsavel) {
        return new Aluno(nome, sobrenome, email);
    }

    @Override
    public Professor criarProfessor(String nome, String sobrenome, String email, String disciplina, String especializacao) {
        if (especializacao == null || especializacao.isEmpty()) {
            throw new IllegalArgumentException("Especialização não pode ser nula ou vazia");
        }
        if (disciplina == null || disciplina.isEmpty()) {
            throw new IllegalArgumentException("Disciplina não pode ser nula ou vazia");
        }
        return new Professor(nome, sobrenome, email, disciplina, especializacao);
    }

    @Override
    public MaterialDidatico criarMaterialDidatico() {
        return new MaterialDidatico("Material de Ensino Médio", new BigDecimal("150.00"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, a classe cliente chamará a factory e terá acesso aos métodos em específico&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class EscolaService {

    EnsinoFactory factoryFundamental = new EnsinoFundamentalFactory();
    EnsinoFactory factoryMedio = new EnsinoMedioFactory();

    public void matricularAluno(){
        //Criando um aluno do ensino fundamental
        Aluno aluno = factoryFundamental.criarAluno("josé","Silva","j@email.com","Maria");
        Professor professor = factoryFundamental.criarProfessor("Mauricio", "Souza", "prof@email",null, null);
        MaterialDidatico materialDidatico = factoryFundamental.criarMaterialDidatico();

        //Criando um aluno do ensino médio
        Aluno alunoMedio = factoryMedio.criarAluno("Bia","Carvalho","bia@email.com",null);
        Professor professorMedio = factoryMedio.criarProfessor("Ana", "Lima", "prof@email","Portugues", "Literatura");
        MaterialDidatico materialDidaticoMedio = factoryMedio.criarMaterialDidatico();
        ///Restante do código
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora você pode estar pensando se valeu a pena, não é mesmo!?&lt;br&gt;
Suponhamos que amanhã surja o ensino técnico, e ele tenha suas próprias regras. Com esta implementação, fica fácil criar uma implementação nova para ele sem alterar as demais. Desta forma, deixamos as regras separadas por cada tipo de matrícula, diminuímos a quantidade de código na classe cliente e, com isso, baixamos a complexidade, risco de bugs e aumentamos a facilidade em manter, entender e escalar o código.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dá pra fazer diferente?
&lt;/h2&gt;

&lt;p&gt;Como em todos os padrões, a implementação pode variar em cima das necessidades. A ideia é ajudar, mas nunca, engessar. &lt;/p&gt;

&lt;p&gt;Neste exemplo poderíamos ainda, criar interfaces para Aluno e Professor. Apesar de incrementar mais classes, isso deixaria o código ainda mais desacoplado e fácil de manter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface Aluno {
String getNome();
// outros métodos comuns
}

public class AlunoFundamental implements Aluno { ... }
public class AlunoMedio implements Aluno { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outro ajuste seria utilizar a sobrecarga de métodos na interface EnsinoFactory. Ao invés de termos um método criarAluno() com todos os parâmetros, poderíamos ter dois. Um com os parâmetros do fundamental e outro com os parâmetros do médio. Desta forma não precisaríamos passar parâmetros desnecessários da classe cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface EnsinoFactory {
  Aluno criarAluno(String nome, String sobrenome, String email, String responsavelLegal); // Fundamental
  Aluno criarAluno(String nome, String sobrenome, String email); // Médio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma terceira possibilidade seria criar uma classe "Matricula", que recebesse Aluno, Professor e Matricula. Depois retornar este objeto em cada factory. Desta forma, ao criar uma matricula os 3 objetos sempre seriam retornados juntos.&lt;/p&gt;

&lt;p&gt;Veja que, existem diversas formas de se pensar e mesmo assim se basear no mesmo padrão. Tudo depende do contexto e necessidade de cada cenário.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desacoplamento&lt;/strong&gt;: o cliente trabalha apenas com interfaces/abstrações, sem conhecer as classes concretas dos produtos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Centralização das regras de negócio&lt;/strong&gt;: as regras específicas de cada família ficam encapsuladas nas fábricas concretas, facilitando manutenção e evolução.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Facilidade para adicionar novas famílias&lt;/strong&gt;: para implementar uma nova variação como o Ensino Técnico, por exemplo, basta criar uma nova fábrica concreta e suas implementações, sem alterar código existente (princípio Open/Closed).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testes&lt;/strong&gt;: facilita a criação dos testes unitários, pois é possível injetar diferentes fábricas em cenários de teste.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexidade&lt;/strong&gt;: aumenta o número de classes no projeto, principalmente se houver muitas famílias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custo&lt;/strong&gt;: Se as diferenças entre famílias forem mínimas, pode ser um “overkill” usar o padrão, pois demanda maior esforço para implementa-lo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tiro pela culatra&lt;/strong&gt;: se precisar adicionar um novo tipo de objeto à família, como coordenador por exemplo, será necessário modificar todas as fábricas abstratas e concretas, violando o princípio Open/Closed nesse aspecto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Curva de aprendizado&lt;/strong&gt;: pode ser mais difícil de entender a princípio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entenda também
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/breno_baudson/factory-method-j44"&gt;Factory Method&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/breno_baudson/singleton-kf2"&gt;Singleton&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>designpatterns</category>
      <category>abstractfactory</category>
      <category>padraodeprojeto</category>
      <category>boaspraticas</category>
    </item>
    <item>
      <title>Desmistificando o Factory Method</title>
      <dc:creator>Breno Baudson</dc:creator>
      <pubDate>Wed, 09 Apr 2025 22:47:13 +0000</pubDate>
      <link>https://dev.to/breno_baudson/factory-method-j44</link>
      <guid>https://dev.to/breno_baudson/factory-method-j44</guid>
      <description>&lt;p&gt;O &lt;em&gt;Factory Method&lt;/em&gt; (ou &lt;em&gt;Método de Fábrica&lt;/em&gt;) é um padrão de projeto do tipo criacional que oferece uma solução elegante para a criação de objetos em sistemas complexos.&lt;/p&gt;

&lt;p&gt;Imagine que você está desenvolvendo um sistema para uma escola que precisa gerenciar alunos, professores e prestadores de serviço, cada um com atributos e comportamentos distintos. Sem um padrão adequado, a criação desses objetos pode se tornar confusa e enrolada como um prato de miojo frio, especialmente se a lógica de criação estiver espalhada por todo o código. O &lt;em&gt;Factory Method&lt;/em&gt; visa resolver esses problemas, definindo uma interface para criar os objetos, promovendo desacoplamento, flexibilidade, facilidade de manutenção e adição de novos tipos de objetos no futuro.&lt;/p&gt;

&lt;p&gt;Façamos um comparativo entre uma implementação inicial sem padrão definido e uma com o padrão Factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Sem padrão definido&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Criei a classe que representa Aluno&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Aluno {
    String nome;
    String sobrenome;
    Long matricula;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criei uma classe Professor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Professor {
    String nome;
    String Sobrenome;
    BigDecimal salario;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A classe cliente, ao precisar instanciar Aluno e/ou professor precisa conhecer a implementação de cada uma...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ServicoPessoa {

    Aluno aluno = new Aluno("Lucas", "Silva", 123456L);
    Professor professor = new Professor("Maria", "Oliveira", new BigDecimal(5000));

    ///// Restante da implementação
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por enquanto é uma implementação padrão e comum, não representa riscos não é mesmo!?&lt;br&gt;
Porém, ainda não criamos a classe para Prestadores de Serviço, que podem se dividir em várias outras como serviço de limpeza, manutenção de equipamentos e etc. A implementação traz repetição de código, acoplamento e riscos para o código. &lt;br&gt;
Imaginemos que, a partir de agora todas as pessoas terão mais um atributo para e-mail. Já temos duas classes para refatorar. Imagine ainda que, teremos mais uma classe de funcionários, que terá os mesmos campos e mais atributos específicos. Olhando por este lado, começamos a encontrar potenciais problemas.&lt;/p&gt;

&lt;p&gt;Pois bem, vamos refatorar este esqueleto e implementar o tal falado Factory.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Implementando Factory&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Uma boa ideia seria criarmos um contrato com os atributos principais, fazendo com que eles não se repitam...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public abstract class Pessoa {
    String nome;
    String sobrenome;
    String email;

    public Pessoa(String nome, String sobrenome, String email) {
        this.nome = nome;
        this.sobrenome = sobrenome;
        this.email = email;
    }

    public Pessoa() {
        // Construtor padrão (sem argumentos)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir daqui, as outras classes extenderem a pessoa, herdarão os atributos comuns e declararão apenas os inerentes a cada uma.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Aluno extends Pessoa {
    Long matricula;

    public Aluno(String nome, String sobrenome, String email) {
        super(nome, sobrenome, email); // Chama o construtor da classe Pessoa   
    }

    public Aluno() {
        // Construtor padrão (sem argumentos)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Professor extends Pessoa {
    BigDecimal salario;

    public Professor(String nome, String sobrenome, String email) {
        super(nome, sobrenome, email); // Chama o construtor de Pessoa        
    }

    public Professor() {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com este primeiro passo já eliminamos a repetição de código e começamos a centralizar a lógica, mas podemos ir além..&lt;br&gt;
Com esta refatoração, o cliente ainda precisa conhecer as classe Aluno e Professor para instancia-las. &lt;strong&gt;É agora que implementamos o padrão Factory!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Digamos que o nosso intuito inicial seja apenas criar um objeto de pessoa, para isso, iniciei criando uma interface de um factory central, que vai gerenciar a criação dos objetos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface PessoaFactory {
Pessoa criarPessoa(String tipo, String nome, String sobrenome, String email);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora crio a implementação desta interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PessoaFactoryManeger implements PessoaFactory {

    @Override
    public Pessoa criarPessoa(String tipo, String nome, String sobrenome, String email) {
        if (tipo.equalsIgnoreCase("aluno")) {
            return new Aluno(nome, sobrenome, email);
        } else if (tipo.equalsIgnoreCase("professor")) {
            return new Professor(nome, sobrenome, email);
        }
        return null;
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desta forma, as subclasses não precisam conhecer a implementação de Aluno nem Professor. Basta chamar a factory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ServicoPessoa {
    PessoaFactory factory = new PessoaFactory();

    public void criarPessoas() {        
        Pessoa aluno = factory.criarPessoa("aluno", "João", "Silva", "joao.silva@email.com");
        Pessoa professor = factory.criarPessoa("professor", "Maria", "Souza", "maria.souza@email.com");
        //demais implementações, como inserir a nota do aluno, etc.
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este é um exemplo mais simples para entendermos a ideia, porém temos várias possibilidades, como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Criar métodos específicos em PessoaFactory, para criar um Professor, por exemplo. Ele já receberia o valor doa tributo salário. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface PessoaFactory {
    Pessoa criarPessoa(String tipo, String nome, String sobrenome, String email);

    Professor criarProfessor(String nome, String sobrenome, String email, BigDecimal salario);  

    Aluno criarAluno(String nome, String sobrenome, String email, Long matricula);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Criar factory especifica para cada tipo de pessoa e delegar as responsabilidades para cada uma. Desta forma, a responsabilidade da PessoaFactoryManeger será apenas decidir qual outra factory chamar. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AlunoFactory implements PessoaFactory {
@Override
public Pessoa criarPessoa(String nome, String sobrenome, String email, Long matricula) {
    return new Aluno(nome, sobrenome, email, matricula);
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estas são possibilidades que, apesar de serem mais trabalhosas na implementação inicial, diminuem muito a complexidade de manutenção, promovem desacoplamento, facilitam implementações de novas implementações de pessoas, proporcionam simplicidade em inserir novos atributos e comportamentos nas classes principais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens do Factory Method:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desacoplamento&lt;/strong&gt;: desacoplou o código do cliente (que usa os objetos) das classes concretas que implementam esses objetos. O cliente interage apenas com a interface, sem precisar conhecer os detalhes de implementação das classes concretas. Isso deixa o código flexível e fácil de manter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexibilidade&lt;/strong&gt;: permitiu adicionar novas pessoas sem alterar o código "base". Desta forma fica muito mais fácil adaptar novas necessidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encapsulamento&lt;/strong&gt;: a utilização do padrão centralizou a lógica de criação dos objetos na fábrica. Facilitou a manutenção e evitou duplicação de código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsabilidade única&lt;/strong&gt;: cada fabrica foi se tornou responsável por criar um tipo especifico de objeto. Esse comportamento segue o principio de responsabilidade única, deixando o código mais modular e fácil de testar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extração de complexidade&lt;/strong&gt;: caso haja complexidade na criação dos objetos, o cliente não precisa ter este conhecimento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desvantagens
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Aumento da complexidade inicial&lt;/strong&gt;: pode aumentar a complexidade inicial do código, principalmente se você tem muitos tipos de objetos para criar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Procriação das classes&lt;/strong&gt;: as classes podem se procriar como coelhos, principalmente se usarmos uma factory para cara objeto. Isso pode tornar o código mais difícil de navegar e entender.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overkill / Exagero&lt;/strong&gt;: em sistemas simples, o padrão Factory pode ser um exagero e aumentar complexidade ao invés de diminuir. Exemplo: se você tem apenas um ou poucos objetos, e não tem previsão de adicionar novos tipos no futuro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custo&lt;/strong&gt;: embora o Factory facilite a manutenção a longo prazo, ele pode aumentar o custo inicial de manutenção, já que a criação das interfaces e classes de fábrica exigem tempo e esforço.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações finais
&lt;/h2&gt;

&lt;p&gt;Os padrões são poderosos e podem trazer muitos benefícios para os sistemas. No entanto, é importante avaliar as vantagens e desvantagens antes de usa-los. Em sistemas simples, o Factory Method pode ser um exagero, porém, em sistemas complexos ele pode ser um aliado valioso. &lt;/p&gt;

&lt;h2&gt;
  
  
  Entenda também
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/breno_baudson/implementando-abstract-factory-44h6"&gt;Abstract Factory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/breno_baudson/singleton-kf2"&gt;Singleton&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>designpatterns</category>
      <category>factory</category>
      <category>boaspraticas</category>
      <category>padraodeprojeto</category>
    </item>
  </channel>
</rss>
