抽象工厂模式
抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
抽象工厂模式结构
-
抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
-
具体产品(Concrete Product)是抽象产品的多种不同类型实现。所有变体都必须实现相应的抽象产品。
-
抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
-
具体工厂 (Concrete Factory)实现抽象工厂的构建方法。每个具体工厂都对应特定产品变体,且仅创建此种产品变体。
-
尽管具体工厂会对具体产品进行初始化,其构建方法签名必须返回相应的抽象产品。这样,使用工厂类的客户端代码就不会与工厂创建的特定产品变体耦合。客户端 (Client)只需通过抽象接口调用工厂和产品对象,就能与任何具体工厂/产品变体交互。
抽象工厂模式通用代码
// 抽象工厂接口声明了一组能返回不同抽象产品的方法。这些产品属于同一个系列
// 且在高层主题或概念上具有相关性。同系列的产品通常能相互搭配使用。系列产
// 品可有多个变体,但不同变体的产品不能搭配使用。
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂可生成属于同一变体的系列产品。工厂会确保其创建的产品能相互搭配
// 使用。具体工厂方法签名会返回一个抽象产品,但在方法内部则会对具体产品进
// 行实例化。
class ConcreteFactory1 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA1();
}
public ProductB createProductB() {
return new ProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public ProductA createProductA() {
return new ProductA2();
}
public ProductB createProductB() {
return new ProductB2();
}
}
// 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
interface ProductA {
// ProductA specific methods
}
class ProductA1 implements ProductA {
// ProductA1 specific methods or fields
}
class ProductA2 implements ProductA {
// ProductA2 specific methods or fields
}
interface ProductB {
// ProductB specific methods
}
class ProductB1 implements ProductB {
// ProductB1 specific methods or fields
}
class ProductB2 implements ProductB {
// ProductB2 specific methods or fields
}
//客户端
public class Client {
public static void main(String[] args) {
// 选择一个具体的工厂实现
AbstractFactory factory = null;
if (conditionForFactory1) {
factory = new ConcreteFactory1();
} else {
factory = new ConcreteFactory2();
}
// 使用工厂对象来创建产品
ProductA productA = factory.createProductA();
ProductB productB = factory.createProductB();
//调用方法等
}
}
抽象工厂模式适合应用场景
-
如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建,在这种情况下,你可以使用抽象工厂。
-
如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。
-
在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。
识别方法: 我们可以通过方法来识别该模式——其会返回一个工厂对象。 接下来, 工厂将被用于创建特定的子组件。
抽象工厂模式优缺点
抽象工厂模式优点:
-
你可以确保同一工厂生成的产品相互匹配。
-
你可以避免客户端和具体产品代码的耦合。
-
单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
-
开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。
抽象工厂模式的缺点: • 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
练手题目
题目描述
小明家新开了两个工厂用来生产家具,一个生产现代风格的沙发和椅子,一个生产古典风格的沙发和椅子,现在工厂收到了一笔订单,请你帮他设计一个系统,描述订单需要生产家具的信息。
输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示订单的数量。
接下来的 N 行,每行输入一个字符串,字符串表示家具的类型。家具类型分为 “modern” 和 “classical” 两种。
输出描述
对于每个积木,输出一行字符串表示该积木的信息。
对于每笔订单,输出字符串表示该订单需要生产家具的信息。
modern订单会输出下面两行字符串
modern chair
modern sofa
classical订单会输出下面两行字符串
classical chair
classical soft
提示信息
在示例中,工厂收到了3笔订单,其中有2笔要求生产modern风格,1笔要求生产classical风格。根据输入的类型,每次订单生产的家具信息被输出到控制台上。
题解
示例代码:
import java.util.Scanner;
// 定义一个家具工厂接口,可以创建椅子和沙发
interface FurnitureFactory{
Chair createChair();
Sofa createSofa();
}
// 实现古典家具工厂,生产古典风格的椅子和沙发
class ClassicalFurnitureFactory implements FurnitureFactory{
@Override
public Chair createChair(){
return new ClassicalChair();
}
@Override
public Sofa createSofa(){
return new ClassicalSofa();
}
}
// 实现现代家具工厂,生产现代风格的椅子和沙发
class ModernFurnitureFactory implements FurnitureFactory{
@Override
public Chair createChair(){
return new ModernChair();
}
@Override
public Sofa createSofa(){
return new ModernSofa();
}
}
// 定义椅子接口,包含生产椅子的方法
interface Chair{
void produceChair();
}
// 实现古典椅子类,继承椅子接口
class ClassicalChair implements Chair{
@Override
public void produceChair(){
System.out.println("classical chair");
}
}
// 实现现代椅子类,继承椅子接口
class ModernChair implements Chair{
@Override
public void produceChair(){
System.out.println("modern chair");
}
}
// 定义沙发接口,包含生产沙发的方法
interface Sofa{
void produceSofa();
}
// 实现古典沙发类,继承沙发接口
class ClassicalSofa implements Sofa{
@Override
public void produceSofa(){
System.out.println("classical sofa");
}
}
// 实现现代沙发类,继承沙发接口
class ModernSofa implements Sofa{
@Override
public void produceSofa(){
System.out.println("modern sofa");
}
}
public class Main{
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
// 创建古典和现代家具工厂实例
FurnitureFactory classicalFurnitureFactory = new ClassicalFurnitureFactory();
FurnitureFactory modernFurnitureFactory = new ModernFurnitureFactory();
// 读取生产次数
int productionCount = scanner.nextInt();
scanner.nextLine();
for (int i = 0; i < productionCount; i++) {
String type = scanner.nextLine();
// 根据用户输入选择相应的家具工厂,并创建家具
FurnitureFactory factory = (type.equals("modern")) ? modernFurnitureFactory : classicalFurnitureFactory;
Chair chair = factory.createChair();
chair.produceChair();
Sofa sofa = factory.createSofa();
sofa.produceSofa();
}
scanner.close();
}
}