Patrón de diseño Abstract Factory en Java

Bienvenido al ejemplo de patrón de diseño Abstract Factory en Java. El patrón de diseño Abstract Factory es uno de los patrones de creación. El patrón de fábrica abstracta es casi similar al patrón de fábrica excepto por el hecho de que es más como una fábrica de fábricas.

Fábrica Abstracta

Si estás familiarizado con el patrón de diseño de fábrica en Java, notarás que tenemos una única clase de fábrica. Esta clase de fábrica devuelve diferentes subclases según la entrada proporcionada, y la clase de fábrica utiliza instrucciones if-else o switch para lograr esto. En el patrón de fábrica abstracta, nos deshacemos del bloque if-else y tenemos una clase de fábrica para cada subclase. Luego, una clase de fábrica abstracta que devolverá la subclase según la clase de fábrica de entrada. Al principio, puede parecer confuso, pero una vez que ves la implementación, es realmente fácil entender y comprender la diferencia menor entre el patrón de fábrica y el patrón de fábrica abstracta. Al igual que en nuestra publicación de patrón de fábrica, usaremos la misma superclase y subclases.

Patrón de diseño de fábrica abstracta: Superclase y Subclases

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;
    }
 
}

Clase de fábrica para cada subclase

En primer lugar, necesitamos crear una interfaz de fábrica abstracta o clase abstracta. ComputerAbstractFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;

public interface ComputerAbstractFactory {

	public Computer createComputer();

}

Observa que el método createComputer() devuelve una instancia de la superclase Computer. Ahora, nuestras clases de fábrica implementarán esta interfaz y devolverán sus respectivas subclases. 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);
	}

}

De manera similar, tendremos una clase de fábrica para la subclase 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);
	}

}

Ahora crearemos una clase consumidora que proporcionará el punto de entrada para que las clases cliente creen subclases. 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();
	}
}

Ten en cuenta que es una clase simple y el método getComputer acepta un argumento de tipo ComputerAbstractFactory y devuelve un objeto Computer. En este punto, la implementación debe estar clara. Escribamos un método de prueba simple y veamos cómo usar la fábrica abstracta para obtener la instancia de las subclases. 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);
	}
}

La salida del programa anterior 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

Aquí tienes el diagrama de clases de la implementación del patrón de diseño de fábrica abstracta.

Beneficios del Patrón de Diseño de Fábrica Abstracta

  • El patrón de diseño de fábrica abstracta proporciona un enfoque para codificar para la interfaz en lugar de la implementación.
  • El patrón de fábrica abstracta es una “fábrica de fábricas” y se puede extender fácilmente para acomodar más productos, por ejemplo, podemos agregar otra subclase Laptop y una fábrica LaptopFactory.
  • El patrón de fábrica abstracta es robusto y evita la lógica condicional del patrón de fábrica.

Ejemplos del Patrón de Diseño de Fábrica Abstracta en JDK

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

Tutorial en Video del Patrón de Diseño de Fábrica Abstracta

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

Puedes descargar el código de los ejemplos desde mi Proyecto en GitHub.

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