设计模式之抽象工厂模式

本片博客主要翻译这篇文章:

https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java

由于翻译水平有限,自认为许多地方翻译不恰当,欢迎各位给出宝贵的建议,建议大家去阅读原文。

引言

抽象工厂模式是一种创建型模式,它和普通工厂模式很相似,一个最大的区别是其包含了工厂的工厂。如果你熟悉 工厂模式 的话,你会发现我们只有唯一一个工厂类。工厂类基于输入的参数,在内部使用 if-else 语句或者是 switch 语句的方式来输出不同的子类。

在抽象工厂设计模式中,我们放弃了 if-else 语句块,为每个子类配备一个工厂类。抽象工厂类现在依据的是输入的工厂类来输出对应的子类。刚开始我们可能会感到很困惑,但是只要我们了解了它的实现,我们就很容易发现它和工厂模式之间的区别。这里我们使用和工厂模式一样的子类和父类。

父类和子类

父类:Computer 类

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 类和 Server 类

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

工厂类和其子类

首先我们需要创建一个抽象工厂接口或者是抽象类

public interface ComputerAbstractFactory{
    public Computer createComputer();
}

这里的 createComputer 方法返回父类 Computer 的一个实例,接着我们的工厂类会实现这个接口并返回各自的子类。

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

同样我们也为 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);
	}
}

最后,我们创建一个类,为客户端提供一个入口来创建子类。

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

我们可以看到这是一个简单的类,其只包含一个 createComputer 方法,接收 ComputerAbstractFactory 作为参数,返回 Computer 类。从这个角度来看,这个实现更加简洁。

这里写一个测试方法来看看如何使用抽象工厂类来创建 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);
	}
}

这是程序的输出:

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

程序的整体类图如下:

设计模式之抽象工厂模式

抽象工厂模式的好处

  1. 抽象工厂模式更加注重面向接口而不是面向实现编程
  2. 抽象工厂模式提供了 “工厂的工厂”,而且可以很容易扩展其他的产品。在这个例子中,我们可以添加另外一个子类 Laptop 和它的工厂类 LaptopFactory。
  3. 工厂方法添加一个子类时,需要在工厂类中添加 if - else 的逻辑判断,才能输出对应的子类,抽象工厂方法很好的避免了这一点。

JDK 中的实现

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

以上就是对全文的翻译,水平有限,请见谅,其中涉及的代码可以到我的 github 上下载。

本片博客主要翻译这篇文章:

https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java

由于翻译水平有限,自认为许多地方翻译不恰当,欢迎各位给出宝贵的建议,建议大家去阅读原文。

引言

抽象工厂模式是一种创建型模式,它和普通工厂模式很相似,一个最大的区别是其包含了工厂的工厂。如果你熟悉 工厂模式 的话,你会发现我们只有唯一一个工厂类。工厂类基于输入的参数,在内部使用 if-else 语句或者是 switch 语句的方式来输出不同的子类。

在抽象工厂设计模式中,我们放弃了 if-else 语句块,为每个子类配备一个工厂类。抽象工厂类现在依据的是输入的工厂类来输出对应的子类。刚开始我们可能会感到很困惑,但是只要我们了解了它的实现,我们就很容易发现它和工厂模式之间的区别。这里我们使用和工厂模式一样的子类和父类。

父类和子类

父类:Computer 类

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 类和 Server 类

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

工厂类和其子类

首先我们需要创建一个抽象工厂接口或者是抽象类

public interface ComputerAbstractFactory{
    public Computer createComputer();
}

这里的 createComputer 方法返回父类 Computer 的一个实例,接着我们的工厂类会实现这个接口并返回各自的子类。

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

同样我们也为 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);
	}
}

最后,我们创建一个类,为客户端提供一个入口来创建子类。

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

我们可以看到这是一个简单的类,其只包含一个 createComputer 方法,接收 ComputerAbstractFactory 作为参数,返回 Computer 类。从这个角度来看,这个实现更加简洁。

这里写一个测试方法来看看如何使用抽象工厂类来创建 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);
	}
}

这是程序的输出:

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

程序的整体类图如下:

设计模式之抽象工厂模式

抽象工厂模式的好处

  1. 抽象工厂模式更加注重面向接口而不是面向实现编程
  2. 抽象工厂模式提供了 “工厂的工厂”,而且可以很容易扩展其他的产品。在这个例子中,我们可以添加另外一个子类 Laptop 和它的工厂类 LaptopFactory。
  3. 工厂方法添加一个子类时,需要在工厂类中添加 if - else 的逻辑判断,才能输出对应的子类,抽象工厂方法很好的避免了这一点。

JDK 中的实现

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

以上就是对全文的翻译,水平有限,请见谅,其中涉及的代码可以到我的 github 上下载。