一 简介
抽象工厂模式(Abstract Factory
):和工厂方法模式不同,抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。
二 意图
抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
三 结构
抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
![image.png](https://img-blog.csdnimg.cn/direct/3677511a631d4c45b691f55af7b14492.png)
- IFactory: 抽象工厂定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口
- Factory(A B …): 具象工厂实现生成不同的具体产品家族,要创建一个产品,客户端主要使用其中一个工厂而不需要实例化任何产品对象
- IProduct(A B …): 抽象产品 不同的抽象产品为不同的产品家族,每一个具体的工厂都能实现一整套的产品
- Product(A1 A2 B1 B2 …): 具象产品角色 对抽象产品的具体分类的实现
四 代码实现
抽象工厂中有一个产品族的概念,以下用一个具体的例子展示出抽象工厂模式的伪代码。具体的例子为两个不同的造车工厂,生产出比亚迪电车和特斯拉电车的过程:
- 比亚迪电车 = 比亚迪电机 + 比亚迪电池
- 特斯拉电车 = 特斯拉电机 + 特斯拉电池
抽象产品角色: IProductA
public interface IMotor {
void doStuff();
}
具象产品角色: Product(A1 A2 …)
public class MotorBYD implements IMotor {
@Override
void doStuff() {
System.out.println("制造-->比亚迪电机");
}
}
public class MotorTesla implements IMotor {
@Override
void doStuff() {
System.out.println("制造-->特斯拉电机");
}
}
抽象产品角色: IProductB
public interface IBattery {
void doStuff();
}
具象产品角色: Product(B1 B2 …)
public class BatteryBYD implements IBattery {
@Override
void doStuff() {
System.out.println("制造-->比亚迪电池");
}
}
public class BatteryTesla implements IBattery {
@Override
void doStuff() {
System.out.println("制造-->特斯拉电池");
}
}
抽象工厂:IFactory
public interface IFactory {
// 制造电机
public IMotor createMotor();
// 制造电池
public IBattery createBattery();
}
具像工厂:Factory(1 2 …)
public class FactoryBYD extends IFactory {
@Override
public IMotor createMotor() {
return new MotorBYD();
}
@Override
public IBattery createBattery() {
return new BatteryBYD();
}
}
public class FactoryTesla extends Factory {
@Override
public IMotor createMotor() {
return new MotorTesla();
}
@Override
public IBattery createBattery() {
return new BatteryTesla();
}
}
客户类调用:
public class Client {
public static void main(String[] args) {
//生产比亚迪汽车
IFactory factoryBYD = new FactoryBYD();
IMotor motorBYD = factoryBYD.createMotor();
motorBYD.doStuff();
IBattery batteryBYD = factoryBYD.createBattery();
batteryBYD.doStuff();
//生产特斯拉汽车
IFactory factoryTesla = new FactoryTesla();
IMotor motorTesla = factoryTesla.createMotor();
motorTesla.doStuff();
IBattery batteryTesla = factoryTesla.createBattery();
batteryTesla.doStuff();
}
}
五 总结
优点:
- 可以确保同一工厂生成的产品相互匹配。
- 可以避免客户端和具体产品代码的耦合。
- 单一职责原则。可以将产品生成代码抽取到同一位置,使得代码易于维护。
- 开闭原则。向应用程序中引入新产品变体时,无需修改客户端代码。
缺点:
- 由于采用该模式需要向应用中引入众多接口和类,代码可能会比之前更加复杂。
使用场景:
- 如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建,在这种情况下,可以使用抽象工厂。
- 如果有一个基于一组抽象方法的类,且其主要功能因此变得不明确,那么在这种情况下可以考虑使用抽象工厂模式。