Java 中的抽象工厂模式:优雅地掌握对象创建
也称为
- 工具包
抽象工厂设计模式的意图
Java 中的抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而无需指定它们的具体类,从而增强了软件设计的模块化和灵活性。
抽象工厂模式的详细解释及现实世界示例
现实世界示例
想象一家家具公司使用 Java 中的抽象工厂模式来生产各种风格的家具:现代、维多利亚和乡村。每种风格都包含椅子、桌子和沙发等产品。为了确保每种风格的一致性,该公司使用了抽象工厂模式。
在这个场景中,抽象工厂是一个用于创建相关家具对象家族(椅子、桌子、沙发)的接口。每个具体工厂(ModernFurnitureFactory、VictorianFurnitureFactory、RusticFurnitureFactory)都实现了抽象工厂接口,并创建一组与特定风格匹配的产品。这样,客户端就可以创建一个完整的现代或维多利亚家具集,而无需担心其实例化的细节。这保持了风格一致性,并允许轻松地将一种风格的家具替换为另一种风格。
通俗地说
工厂的工厂;一个将单个但相关/依赖的工厂分组在一起的工厂,而不指定它们的具体类。
维基百科说
抽象工厂模式提供了一种方式来封装一组具有共同主题的单个工厂,而不指定它们的具体类
Java 中抽象工厂模式的编程示例
为了使用 Java 中的抽象工厂模式创建一个王国,我们需要具有共同主题的对象。精灵王国需要精灵国王、精灵城堡和精灵军队,而兽人王国需要兽人国王、兽人城堡和兽人军队。王国中的对象之间存在依赖关系。
将上面的王国示例翻译过来。首先,我们有一些接口和王国中对象的实现。
public interface Castle {
String getDescription();
}
public interface King {
String getDescription();
}
public interface Army {
String getDescription();
}
// Elven implementations ->
public class ElfCastle implements Castle {
static final String DESCRIPTION = "This is the elven castle!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfKing implements King {
static final String DESCRIPTION = "This is the elven king!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfArmy implements Army {
static final String DESCRIPTION = "This is the elven Army!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// Orcish implementations similarly -> ...
然后我们有王国工厂的抽象和实现。
public interface KingdomFactory {
Castle createCastle();
King createKing();
Army createArmy();
}
public class ElfKingdomFactory implements KingdomFactory {
@Override
public Castle createCastle() {
return new ElfCastle();
}
@Override
public King createKing() {
return new ElfKing();
}
@Override
public Army createArmy() {
return new ElfArmy();
}
}
// Orcish implementations similarly -> ...
现在,我们可以为不同的王国工厂设计一个工厂。在这个例子中,我们创建了FactoryMaker
,负责返回ElfKingdomFactory
或OrcKingdomFactory
的实例。客户端可以使用FactoryMaker
来创建所需的具体工厂,该工厂反过来将生成不同的具体对象(派生自Army
、King
、Castle
)。在这个例子中,我们还使用了一个枚举来参数化客户端将请求的王国工厂类型。
public static class FactoryMaker {
public enum KingdomType {
ELF, ORC
}
public static KingdomFactory makeFactory(KingdomType type) {
return switch (type) {
case ELF -> new ElfKingdomFactory();
case ORC -> new OrcKingdomFactory();
};
}
}
以下是示例应用程序的主要函数
LOGGER.info("elf kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
LOGGER.info(kingdom.getArmy().getDescription());
LOGGER.info(kingdom.getCastle().getDescription());
LOGGER.info(kingdom.getKing().getDescription());
LOGGER.info("orc kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
LOGGER.info(kingdom.getArmy().getDescription());
LOGGER.info(kingdom.getCastle().getDescription());
LOGGER.info(kingdom.getKing().getDescription());
程序输出
07:35:46.340 [main] INFO com.iluwatar.abstractfactory.App -- elf kingdom
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven army!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven castle!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven king!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- orc kingdom
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc army!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc castle!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc king!
抽象工厂模式类图
何时在 Java 中使用抽象工厂模式
在以下情况下使用 Java 中的抽象工厂模式
- 系统应独立于其产品的创建、组合和表示方式。
- 您需要使用多个产品系列之一配置系统。
- 必须使用相关产品对象的家族,以强制执行一致性。
- 您想提供一个产品类库,只公开其接口,而不是其实现。
- 依赖项的生命周期比消费者的生命周期短。
- 需要使用运行时值或参数来构造依赖项。
- 您需要在运行时从家族中选择要使用的产品。
- 添加新产品或家族不需要更改现有代码。
抽象工厂模式 Java 教程
抽象工厂模式的优点和权衡
优点
灵活:在产品系列之间轻松切换,无需代码修改。
解耦:客户端代码只与抽象接口交互,从而提高了可移植性和可维护性。
可重用性:抽象工厂和产品促进跨项目的组件重用。
可维护性:对单个产品系列的更改是本地化的,简化了更新。
权衡
复杂性:定义抽象接口和具体工厂会增加初始开销。
间接性:客户端代码通过工厂间接地与产品交互,这可能会降低透明度。
Java 中抽象工厂模式的现实世界应用
- Java Swing 的
LookAndFeel
类,用于提供不同的外观选项。 - Java 抽象窗口工具包 (AWT) 中的各种实现,用于创建不同的 GUI 组件。
- javax.xml.parsers.DocumentBuilderFactory
- javax.xml.transform.TransformerFactory
- javax.xml.xpath.XPathFactory