一、概念
先有一个抽象工厂,然后去生成其他具体工厂,然后用其他具体工厂创建对象。
客户类和工厂类分开。消费者任何时候需要某套产品集合时,只需向抽象工厂请求即可。抽象工厂会再向具体的工厂生产出符合产品集规格的产品。(来源于百度百科)
二、代码
上例子:
要生产一台电脑,定义一个抽象工厂(Factory),然后用该抽象工厂去创建一个生产主机的工厂(CaseFactory),再使用具体的工厂去生产零件(Cpu、Mem、Gpu、Disk、Computer),最后组装电脑。
Component:零件类
public abstract class Component {
/**
* 成本价
*/
protected int cost;
public Component(int cost) {
this.cost = cost;
}
/**
* 零件信息
* @return
*/
public abstract String info();
}
Cpu:CPU类
public abstract class Cpu extends Component{
public Cpu(int cost) {
super(cost);
}
}
Mem:内存条类
public abstract class Mem extends Component {
/**
* 内存大小
*/
protected String mem;
public Mem(int cost,String mem) {
super(cost);
this.mem = mem;
}
}
Gpu:显卡类
public abstract class Gpu extends Component{
/**
* 显存
*/
protected String mem;
public Gpu(int cost,String mem) {
super(cost);
this.mem = mem;
}
}
Disk:硬盘类
public abstract class Disk extends Component{
/**
* 存储大小
*/
protected String storageSize;
/**
* 硬盘类型
*/
protected String type;
public Disk(int cost,String storageSize,String type) {
super(cost);
this.storageSize = storageSize;
this.type = type;
}
}
Computer:主机箱/笔记本类
public abstract class Computer extends Component{
//CPU
protected Cpu cpu;
//显卡
protected Gpu gpu;
//内存条
protected Mem mem;
//硬盘
protected Disk disk;
//总价
protected int totalCost;
public Computer(int cost) {
super(cost);
this.totalCost = cost;
}
/**
* 安装零件
*/
public void fitComponent(Cpu cpu,Gpu gpu,Mem mem,Disk disk){
this.cpu = cpu;
totalCost += cpu.cost;
this.gpu = gpu;
totalCost += gpu.cost;
this.mem = mem;
totalCost += mem.cost;
this.disk = disk;
totalCost += disk.cost;
}
}
Factory:抽象工厂
public abstract class Factory {
//生成具体工厂的静态方法
public static Factory getFactory(String clazz){
try {
return (Factory) Class.forName(clazz).newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
/**
* 创建CPU
*/
public abstract Cpu createCpu(int cost);
/**
* 创建显卡
*/
public abstract Gpu createGpu(int cost,String mem);
/**
* 创建内存条
*/
public abstract Mem createMem(int cost,String mem);
/**
* 创建硬盘
*/
public abstract Disk createDisk(int cost,String storageSize,String type);
/**
* 创建一个主机/笔记本
*/
public abstract Computer createComputer(int cost);
}
到此,抽象部分定义完毕,接下来定义具体部分
IntelCpu:英特尔CPU
public class IntelCpu extends Cpu {
/**
* 型号
*/
private String model;
public IntelCpu(int cost,String model) {
super(cost);
this.model = model;
}
@Override
public String info() {
return "CPU [ Intel " + model + " ] "+cost +"元";
}
}
SansungMem:三星内存条
public class SansungMem extends Mem {
public SansungMem(int cost, String mem) {
super(cost, mem);
}
@Override
public String info() {
return "内存 [ 三星 "+ mem +" ] "+cost+"元";
}
}
NvidiaGpu:英伟达显卡
public class NvidiaGpu extends Gpu {
/**
* 型号
*/
private String model;
public NvidiaGpu(int cost, String mem,String model) {
super(cost, mem);
this.model = model;
}
@Override
public String info() {
return "显卡 [ NVIDIA " + model + " " + mem + " ] " +cost+"元";
}
}
SansungDisk:三星硬盘
public class SansungDisk extends Disk {
public SansungDisk(int cost, String storageSize, String type) {
super(cost, storageSize, type);
}
@Override
public String info() {
return "硬盘 [ 三星 " + storageSize + " " + type + " ] " + cost+"元";
}
}
CaseComputer:主机箱
public class CaseComputer extends Computer {
private static final String LINEFEED = "\r\n";
public CaseComputer(int cost) {
super(cost);
}
@Override
public String info() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("主机信息:");
stringBuilder.append(LINEFEED);
stringBuilder.append("总价:").append(totalCost).append("元");
stringBuilder.append(LINEFEED);
stringBuilder.append(cpu.info());
stringBuilder.append(LINEFEED);
stringBuilder.append(mem.info());
stringBuilder.append(LINEFEED);
stringBuilder.append(gpu.info());
stringBuilder.append(LINEFEED);
stringBuilder.append(disk.info());
return stringBuilder.toString();
}
}
CaseFactory:组装机工厂
public class CaseFactory extends Factory {
@Override
public Cpu createCpu(int cost) {
return new IntelCpu(cost,"2.9 GHz Intel Core i7");
}
@Override
public Gpu createGpu(int cost, String mem) {
return new NvidiaGpu(cost,mem,"GTX2080 Ti");
}
@Override
public Mem createMem(int cost, String mem) {
return new SansungMem(cost,mem);
}
@Override
public Disk createDisk(int cost, String storageSize, String type) {
return new SansungDisk(cost,storageSize,type);
}
@Override
public Computer createComputer(int cost) {
return new CaseComputer(cost);
}
}
到此为止,具体的零件类以及具体的工厂(组装机工厂)已经都有了,接下来就是生产一台主机
main方法测试
public static void main(String[] args) {
Factory factory = Factory.getFactory("designpattern.abstract_factory_pattern.CaseFactory");
Computer computer = factory.createComputer(1000);
Cpu cpu = factory.createCpu(1700);
Gpu gpu = factory.createGpu(2300,"6G");
Mem mem = factory.createMem(400,"16G");
Disk disk = factory.createDisk(450,"256G","固态");
computer.fitComponent(cpu,gpu,mem,disk);
String info = computer.info();
System.out.println(info);
}
结果
主机信息:
总价:5850元
CPU [ Intel 2.9 GHz Intel Core i7 ] 1700元
内存 [ 三星 16G ] 400元
显卡 [ NVIDIA GTX2080 Ti 6G ] 2300元
硬盘 [ 三星 256G 固态 ] 450元
三、结构

四、优劣
抽象模块定义好后,很容易扩展新的具体工厂,且使用方代码不怎么需要改,如上main方法,只传入的一个具体工厂类名,就可以运作。
但新增零件就比较麻烦(例如新增加一个风扇,则抽象层需要增加一个抽象风扇,抽象工厂需要增加一个生产风扇的方法,且具体实现层也需要增加具体的实现,并且已有的具体工厂也得修改)。
Spring使用了大量的抽象工厂模式。