Búsqueda de sitios web

Patrón de diseño de fábrica abstracto en Java


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

Fábrica abstracta

Superclases y subclases de patrón de diseño de fábrica abstracto

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

Servidor.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, debemos crear una interfaz de fábrica abstracta o una clase abstracta. ComputerAbstractFactory.java

package com.journaldev.design.abstractfactory;

import com.journaldev.design.model.Computer;

public interface ComputerAbstractFactory {

	public Computer createComputer();

}

Observe 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 su respectiva subclase. 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 de consumidor que proporcionará el punto de entrada para que las clases de 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();
	}
}

Tenga en cuenta que es una clase simple y el método getComputer acepta el argumento ComputerAbstractFactory y devuelve el objeto Computer. En este punto, la implementación debe ser 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

Beneficios del patrón de diseño de fábrica abstracta

  • El patrón de diseño de Abstract Factory proporciona un enfoque del código para la interfaz en lugar de la implementación.
  • El patrón Abstract Factory es \fábrica de fábricas” y se puede ampliar fácilmente para admitir más productos, por ejemplo, podemos agregar otra subclase Laptop y una LaptopFactory de fábrica.
  • El patrón Abstract Factory es sólido y evita la lógica condicional del patrón Factory.

Ejemplos de patrones de diseño de fábrica abstracta en JDK

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

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

Recientemente subí un video en YouTube para un patrón de diseño de fábrica abstracto. En el video, analizo cuándo y cómo implementar un patrón de fábrica abstracto. También he discutido cuál es la diferencia entre el patrón de fábrica y el patrón de diseño de fábrica abstracto. https://youtu.be/BPkYkyVWOaw

Puede descargar el código de ejemplos de mi Proyecto GitHub.

Artículos relacionados: