设计模式-抽象工厂模式(Abstract Factory Pattern)
一、定义
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
二、概念解释
想充分了解抽象工厂我们需要从工厂方法聊起,工厂方法的定义是为创建一个对象定义一个接口,比如我要一个Intel的cpu,我就需要创建一个Intel的cpu工厂,我要一个Intel的gpu,我就需要一个Intel的gpu工厂,我要创建单个对象,就需要有对应的工厂来负责创建。而对于抽象工厂方法来说,其定义是为创建一组相关或相互依赖的对象提供一个接口,我们将相关或相互依赖的对象称为对象族,比如我需要一台组装电脑,我就需要cpu、gpu、主板、电源、机箱、内存条、硬盘等等,我们将这些组件抽象一层,让具体的制造商去实现他们,不同制造商生产的各个组件的组合就是一个个产品族
三、场景
装配一台主机,就需要不同的电脑部件,而每一个部件都有不同的制造商就相当于每一个部件都是一个产品族,这里就可以用抽象工厂的方式去组装一台电脑,选择不同制造商制造的同一产品族的硬件,示例代码仅以部分电脑组件为例(CPU和显卡)
四、实现
1、类图
2、代码实现
首先定义两个产品族 CPU 和 GPU
public interface CPU{
/**
* 获取产品描述
*/
String getDescription();
}
public interface GPU {
/**
* 获取产品描述
*/
String getDescription();
}
不同的制造商分别定义自己的产品
// Intel制造商
public class IntelCPU implement CPU {
private static final String DESCRIPTION = "This is intel CPU";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// Intel制造商
public class InterGPU implements GPU {
private static final String DESCRIPTION = "This is inter gpu";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// AMD制造商
public class AMDCPU implements CPU {
static final String DESCRIPTION = "This is amd cpu";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// AMD制造商
public class AMDGPU implements GPU {
private static final String DESCRIPTION = "This is amd gpu";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
定义负责生产组装电脑的抽象工厂
// 示例中仅生产了部分组件
public interface ComputerDIYFactory {
/**
* 生产CPU
* @return CPU产品 不指定具体类
*/
CPU createCPU();
/**
* 生产GPU
* @return GPU产品 不指定具体类
*/
GPU createGPU();
}
定义抽象工厂的实现类
public class IntelFactory implements ComputerDIYFactory {
@Override
public CPU createCPU() {
return new IntelCPU();
}
@Override
public GPU createGPU() {
return new InterGPU();
}
}
public class AMDFactory implements ComputerDIYFactory {
@Override
public CPU createCPU() {
return new AMDCPU();
}
@Override
public GPU createGPU() {
return new AMDGPU();
}
}
实际的组装电脑对象 承上启下 解耦
@Getter
@Setter
public class ComputerDIY {
private CPU cpu;
private GPU gpu;
public static class FactoryMaker {
public enum ComputerDIYManufacturer {
INTEL, AMD;
}
public static ComputerDIYFactory makeFactory(ComputerDIYManufacturer manufacturer) {
switch (manufacturer) {
case INTEL:
return new IntelFactory();
case AMD:
return new AMDFactory();
default:
throw new IllegalArgumentException("manufacturer not supported");
}
}
}
}
编写测试类
@SpringBootTest
public class AbstractFactoryTest {
private final ComputerDIY computerDIY = new ComputerDIY();
@Test
public void Test() {
final ComputerDIYFactory factory = ComputerDIY.FactoryMaker.makeFactory(ComputerDIY.FactoryMaker.ComputerDIYManufacturer.INTEL);
computerDIY.setCpu(factory.createCPU());
computerDIY.setGpu(factory.createGPU());
System.out.println(computerDIY.getCpu().getDescription());
System.out.println(computerDIY.getGpu().getDescription());
final ComputerDIYFactory diyFactory = ComputerDIY.FactoryMaker.makeFactory(ComputerDIY.FactoryMaker.ComputerDIYManufacturer.AMD);
computerDIY.setCpu(diyFactory.createCPU());
computerDIY.setGpu(diyFactory.createGPU());
System.out.println(computerDIY.getCpu().getDescription());
System.out.println(computerDIY.getGpu().getDescription());
}
}
五、优缺点
优点
- 如示例代码的例子,当我们代码中有产品族这种抽象概念时,使用抽象工厂模式会带来很大的便利
- 对于产品等级的扩展是很方便的,比如我们要再加一个其他的制造商,只需要定义自己的产品实现、工厂实现
缺点
- 对于产品族的扩展不符合开闭原则,比如当我们需要增加一个固态硬盘产品族时,抽象工厂就会新增一个抽象方法,导致已有两个实现类都要修改