Java抽象工厂设计模式
定义
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
对应角色
- 抽象工厂:定义了创建产品对象的接口。
- 具体工厂:实现了抽象工厂中定义的接口,负责创建具体的产品对象。
- 抽象产品:定义了产品对象的公共接口。
- 具体产品:实现了抽象产品中定义的接口,由具体工厂来创建
优缺点
优点
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点
文章来源:https://uudwc.com/A/dMWj8
- 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
应用场景
- 忽略创建细节:客户端不关心产品实例如何被创建,实现等细节;
- 创建产品族:强调一系列相关的产品对象,一般是同一个产品族,一起使用;
- 创建对象需要大量重复的代码2。
例如,Java 的 AWT 中的 Button 和 Text 等构件在 Windows 和 UNIX 中的本地实现是不同的3。文章来源地址https://uudwc.com/A/dMWj8
实例
// 抽象产品A
interface ProductA {
void use();
}
// 具体产品A1
class ProductA1 implements ProductA {
@Override
public void use() {
System.out.println("使用产品A1");
}
}
// 具体产品A2
class ProductA2 implements ProductA {
@Override
public void use() {
System.out.println("使用产品A2");
}
}
// 抽象产品B
interface ProductB {
void use();
}
// 具体产品B1
class ProductB1 implements ProductB {
@Override
public void use() {
System.out.println("使用产品B1");
}
}
// 具体产品B2
class ProductB2 implements ProductB {
@Override
public void use() {
System.out.println("使用产品B2");
}
}
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
productA1.use();
ProductB productB1 = factory1.createProductB();
productB1.use();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
productA2.use();
ProductB productB2 = factory2.createProductB();
productB2.use();
}
}