Padrão de Projeto de Fábrica Abstrata em Java

Bem-vindo ao exemplo do Padrão de Projeto Abstract Factory em Java. O padrão de design Abstract Factory é um dos padrões de criação. O padrão Abstract Factory é quase semelhante ao Padrão de Fábrica, exceto pelo fato de que é mais como uma fábrica de fábricas.

Fábrica Abstrata

Se você está familiarizado com padrão de design de fábrica em Java, notará que temos uma única classe Factory. Esta classe de fábrica retorna diferentes subclasses com base na entrada fornecida, e a classe de fábrica utiliza instruções if-else ou switch para conseguir isso. No padrão Abstract Factory, eliminamos o bloco if-else e temos uma classe de fábrica para cada subclasse. Em seguida, uma classe de fábrica abstrata que retornará a subclasse com base na classe de fábrica de entrada. A princípio, pode parecer confuso, mas uma vez que você veja a implementação, é realmente fácil compreender e entender a pequena diferença entre o padrão de Fábrica e o padrão Abstract Factory. Assim como em nossa postagem sobre o padrão de fábrica, usaremos a mesma superclasse e subclasses.

Padrão de Design Abstract Factory Super Classe e Subclasses

Computer.java

package com.journaldev.design.model;
 
public abstract class Computer {
     
    public abstract String getRAM();
    public abstract String getHDD();
    public abstract String getCPU();
     
    @Override
    public String toString(){
        return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
    }
}

PC.java

package com.journaldev.design.model;
 
public class PC extends Computer {
 
    private String ram;
    private String hdd;
    private String cpu;
     
    public PC(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public String getCPU() {
        return this.cpu;
    }
 
}

Server.java

package com.journaldev.design.model;
 
 
public class Server extends Computer {
 
    private String ram;
    private String hdd;
    private String cpu;
     
    public Server(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public String getCPU() {
        return this.cpu;
    }
 
}

Classe de Fábrica para cada subclasse

Primeiro, precisamos criar uma interface de Fábrica Abstrata ou classe abstrata. ComputerAbstractFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;

public interface ComputerAbstractFactory {

	public Computer createComputer();

}

Observe que o método createComputer() está retornando uma instância da super classe Computer. Agora, nossas classes de fábrica implementarão essa interface e retornarão suas respectivas subclasses. PCFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;
import com.journaldev.design.model.PC;

public class PCFactory implements ComputerAbstractFactory {

	private String ram;
	private String hdd;
	private String cpu;
	
	public PCFactory(String ram, String hdd, String cpu){
		this.ram=ram;
		this.hdd=hdd;
		this.cpu=cpu;
	}
	@Override
	public Computer createComputer() {
		return new PC(ram,hdd,cpu);
	}

}

Da mesma forma, teremos uma classe de fábrica para a subclasse Server. ServerFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;
import com.journaldev.design.model.Server;

public class ServerFactory implements ComputerAbstractFactory {

	private String ram;
	private String hdd;
	private String cpu;
	
	public ServerFactory(String ram, String hdd, String cpu){
		this.ram=ram;
		this.hdd=hdd;
		this.cpu=cpu;
	}
	
	@Override
	public Computer createComputer() {
		return new Server(ram,hdd,cpu);
	}

}

Agora, vamos criar uma classe consumidora que fornecerá o ponto de entrada para as classes cliente criarem subclasses. ComputerFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;

public class ComputerFactory {

	public static Computer getComputer(ComputerAbstractFactory factory){
		return factory.createComputer();
	}
}

Observe que é uma classe simples e o método getComputer está aceitando o argumento ComputerAbstractFactory e retornando o objeto Computer. Neste ponto, a implementação deve estar clara. Vamos escrever um método de teste simples e ver como usar a fábrica abstrata para obter a instância das subclasses. TestDesignPatterns.java

package com.journaldev.design.test;

import com.journaldev.design.abstractfactory.PCFactory;
import com.journaldev.design.abstractfactory.ServerFactory;
import com.journaldev.design.factory.ComputerFactory;
import com.journaldev.design.model.Computer;

public class TestDesignPatterns {

	public static void main(String[] args) {
		testAbstractFactory();
	}

	private static void testAbstractFactory() {
		Computer pc = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new PCFactory("2 GB","500 GB","2.4 GHz"));
		Computer server = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new ServerFactory("16 GB","1 TB","2.9 GHz"));
		System.out.println("AbstractFactory PC Config::"+pc);
		System.out.println("AbstractFactory Server Config::"+server);
	}
}

A saída do programa acima será:

AbstractFactory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
AbstractFactory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

Aqui está o diagrama de classe da implementação do padrão de design de fábrica abstrata.

Benefícios do Padrão de Design de Fábrica Abstrata

  • O padrão de design de fábrica abstrata fornece uma abordagem para codificar para interface em vez de implementação.
  • O padrão de fábrica abstrata é um “fábrica de fábricas” e pode ser facilmente estendido para acomodar mais produtos, por exemplo, podemos adicionar outra subclasse Laptop e uma fábrica LaptopFactory.
  • O padrão de fábrica abstrata é robusto e evita a lógica condicional do padrão de fábrica.

Exemplos de Padrão de Projeto Abstract Factory no JDK

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()
  • javax.xml.transform.TransformerFactory#newInstance()
  • javax.xml.xpath.XPathFactory#newInstance()

Tutorial em Vídeo sobre o Padrão de Projeto Abstract Factory

I recently uploaded a video on YouTube for abstract factory design pattern. In the video, I discuss when and how to implement an abstract factory pattern. I have also discussed what is the difference between the factory pattern and abstract factory design pattern. https://youtu.be/BPkYkyVWOaw

Você pode baixar os exemplos de código do meu Projeto GitHub.

Source:
https://www.digitalocean.com/community/tutorials/abstract-factory-design-pattern-in-java