【设计模式】【创建型模式】抽象工厂模式(Abstract Factory)

简介: 一、入门 什么是抽象工厂模式? 抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体的类。 简单来说,抽象工厂模式是工厂方法模式的升级版,它能够创建一组相

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD

🔥 2025本人正在沉淀中... 博客更新速度++

👍 欢迎点赞、收藏、关注,跟上我的更新节奏

🎵 当你的天空突然下了大雨,那是我在为你炸乌云

一、入门

什么是抽象工厂模式?

抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体的类。
简单来说,抽象工厂模式是工厂方法模式的升级版,它能够创建一组相关的对象,而工厂方法模式只能创建一种对象。

为什么要抽象工厂模式?

假设你要购买一套家具(沙发、茶几、电视柜),并且希望这些家具的风格保持一致(比如现代风格或古典风格)。如果没有抽象工厂模式,下面是没有抽象工厂的实现:

// 现代风格沙发
class ModernSofa {
   
    public void lieOn() {
   
        System.out.println("躺在现代风格沙发上");
    }
}

// 古典风格沙发
class ClassicSofa {
   
    public void lieOn() {
   
        System.out.println("躺在古典风格沙发上");
    }
}

// 现代风格茶几
class ModernCoffeeTable {
   
    public void putOn() {
   
        System.out.println("在现代风格茶几上放东西");
    }
}

// 古典风格茶几
class ClassicCoffeeTable {
   
    public void putOn() {
   
        System.out.println("在古典风格茶几上放东西");
    }
}

// 客户端代码
public class FurnitureShop {
   
    public static void main(String[] args) {
   
        // 选择现代风格
        ModernSofa modernSofa = new ModernSofa();
        ModernCoffeeTable modernCoffeeTable = new ModernCoffeeTable();

        modernSofa.lieOn();
        modernCoffeeTable.putOn();

        // 选择古典风格
        ClassicSofa classicSofa = new ClassicSofa();
        ClassicCoffeeTable classicCoffeeTable = new ClassicCoffeeTable();

        classicSofa.lieOn();
        classicCoffeeTable.putOn();
    }
}

存在问题:

  1. 风格一致性难以保证:
    • 如果客户端代码不小心混用了不同风格的对象(比如现代风格沙发 + 古典风格茶几),会导致风格不一致。
ModernSofa sofa = new ModernSofa();
ClassicCoffeeTable table = new ClassicCoffeeTable(); // 风格不一致!
  1. 代码重复:
    • 每次创建一组家具时,都需要重复编写类似的代码。
      ModernSofa sofa = new ModernSofa();
      ModernCoffeeTable table = new ModernCoffeeTable();
    • 如果家具种类增多(比如增加电视柜、餐桌),代码会变得更加冗长。
  2. 难以扩展:
    • 如果新增一种风格(比如北欧风格),需要修改客户端代码,手动创建新的对象:
      NordicSofa sofa = new NordicSofa();
      NordicCoffeeTable table = new NordicCoffeeTable();
    • 这会违反开闭原则(对扩展开放,对修改关闭)。
  3. 客户端代码与具体类耦合:
    • 客户端代码直接依赖具体的家具类(如ModernSofa、ClassicCoffeeTable),如果具体类发生变化(比如类名修改),客户端代码也需要跟着修改。

如何实现抽象工厂模式?

  1. 抽象工厂(Abstract Factory):声明一组创建产品对象的方法,每个方法对应一种产品。
  2. 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建具体的产品对象。
  3. 抽象产品(Abstract Product):声明产品的接口。
  4. 具体产品(Concrete Product):实现抽象产品接口,定义具体产品的行为。

【案例】家具城 - 改

image.png

抽象产品(Abstract Product):沙发、茶几。

// 沙发
interface Sofa {
   
    void lieOn();
}

// 茶几
interface CoffeeTable {
   
    void putOn();
}

具体产品(Concrete Product): 现代沙发、古典风格沙发、现代风格茶几、古典风格茶几。

// 具体产品:现代风格沙发
class ModernSofa implements Sofa {
   
    public void lieOn() {
   
        System.out.println("躺在现代风格沙发上");
    }
}

// 具体产品:古典风格沙发
class ClassicSofa implements Sofa {
   
    public void lieOn() {
   
        System.out.println("躺在古典风格沙发上");
    }
}

// 具体产品:现代风格茶几
class ModernCoffeeTable implements CoffeeTable {
   
    public void putOn() {
   
        System.out.println("在现代风格茶几上放东西");
    }
}

// 具体产品:古典风格茶几
class ClassicCoffeeTable implements CoffeeTable {
   
    public void putOn() {
   
        System.out.println("在古典风格茶几上放东西");
    }
}

抽象工厂(Abstract Factory): 家具工厂

interface FurnitureFactory {
   
    Sofa createSofa();
    CoffeeTable createCoffeeTable();
}

具体工厂(Concrete Factory):现代风格家具工厂、古典风格家具工厂。

// 具体工厂:现代风格家具工厂
class ModernFurnitureFactory implements FurnitureFactory {
   
    public Sofa createSofa() {
   
        return new ModernSofa();
    }

    public CoffeeTable createCoffeeTable() {
   
        return new ModernCoffeeTable();
    }
}

// 具体工厂:古典风格家具工厂
class ClassicFurnitureFactory implements FurnitureFactory {
   
    public Sofa createSofa() {
   
        return new ClassicSofa();
    }

    public CoffeeTable createCoffeeTable() {
   
        return new ClassicCoffeeTable();
    }
}

客户端

public class FurnitureShop {
   
    private Sofa sofa;
    private CoffeeTable coffeeTable;

    public FurnitureShop(FurnitureFactory factory) {
   
        sofa = factory.createSofa();
        coffeeTable = factory.createCoffeeTable();
    }

    public void useFurniture() {
   
        sofa.lieOn();
        coffeeTable.putOn();
    }

    public static void main(String[] args) {
   
        // 选择现代风格家具工厂
        FurnitureFactory modernFactory = new ModernFurnitureFactory();
        FurnitureShop shop = new FurnitureShop(modernFactory);
        shop.useFurniture();

        // 选择古典风格家具工厂
        FurnitureFactory classicFactory = new ClassicFurnitureFactory();
        shop = new FurnitureShop(classicFactory);
        shop.useFurniture();
    }
}

抽象工厂模式和工厂方法的区别

场景 工厂方法模式 抽象工厂模式
创建目标 单个产品(如沙发) 一组相关产品(如沙发、茶几、电视柜)
风格一致性 无法保证 保证一组对象的风格一致
类的数量 每个产品需要一个工厂接口和具体工厂类 每个产品家族需要一个具体工厂类
客户端代码复杂度 需要分别调用多个工厂 只需调用一个工厂即可创建一组对象
适用场景 单一产品的创建 一组相关或依赖对象的创建

二、抽象工厂模式在框架源码中的运用

JDBC 中的 java.sql.Connection

JDBC(Java Database Connectivity)是Java中用于操作数据库的标准API,其中的 Connection 和 Statement 等接口也体现了抽象工厂模式。

public class JDBCExample {
   
    public static void main(String[] args) throws Exception {
   
        // 获取数据库连接(抽象工厂)
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");

        // 创建Statement(具体产品)
        Statement statement = connection.createStatement();

        // 执行查询
        ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

        // 处理结果
        while (resultSet.next()) {
   
            System.out.println(resultSet.getString("username"));
        }
    }
}

抽象工厂模式的应用

  • 抽象工厂:Connection 是一个抽象工厂,定义了创建 Statement、PreparedStatement等方法。
  • 具体工厂:不同的数据库驱动(如MySQL、Oracle)提供了具体的 Connection 实现。
  • 产品家族:Statement、PreparedStatement、ResultSet 是相关的产品,用于执行SQL语句和处理结果。

Spring 框架中的 BeanFactory

Spring 框架的核心容器 BeanFactory 也是一个典型的抽象工厂模式应用。

public class SpringExample {
   
    public static void main(String[] args) {
   
        // 加载Spring配置文件
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));

        // 获取Bean(具体产品)
        MyService myService = (MyService) factory.getBean("myService");
        myService.execute();
    }
}

抽象工厂模式的应用

  • 抽象工厂:BeanFactory 是一个抽象工厂,定义了获取Bean的方法(如getBean)。
  • 具体工厂:XmlBeanFactory 是一个具体工厂,负责从XML配置文件中创建和管理Bean。
  • 产品家族:Spring容器管理的Bean(如 MyService)是相关的产品,它们可能相互依赖或协作。

三、总结

抽象工厂模式的优点

  1. 保证产品家族的一致性:
    • 抽象工厂模式确保创建的对象是同一家族的,比如现代风格的沙发、茶几、电视柜,避免了风格不一致的问题。
  2. 解耦客户端代码:
    • 客户端代码只依赖于抽象工厂和抽象产品接口,不依赖于具体的实现类,符合依赖倒置原则。
  3. 符合开闭原则:
    • 新增产品家族(如新增北欧风格家具)时,只需增加新的具体工厂类,不需要修改现有代码。
  4. 简化客户端代码:
    • 客户端不需要关心具体对象的创建细节,只需要调用工厂方法即可。
  5. 提高代码可维护性:
    • 将对象的创建逻辑集中到工厂中,便于统一管理和维护。

抽象工厂模式的缺点

  1. 类的数量增加:
    • 每增加一个产品家族,就需要增加一组具体工厂类和具体产品类,可能导致类的数量爆炸。
  2. 扩展产品类型困难:
    • 如果需要在现有产品家族中新增产品类型(比如在家具家族中新增“餐桌”),需要修改抽象工厂接口及其所有具体工厂类,违反了开闭原则。
  3. 复杂性增加:
    • 对于简单的对象创建场景,使用抽象工厂模式可能会引入不必要的复杂性。
  4. 理解难度较高:
    • 抽象工厂模式涉及多个抽象层(抽象工厂、抽象产品、具体工厂、具体产品),初学者可能难以理解。

抽象工厂模式的适用场景

抽象工厂模式适用于以下场景:

  1. 需要创建一组相关或依赖的对象:
    • 比如跨平台的UI组件(Windows按钮、Mac按钮)、家具家族(现代风格沙发、茶几)、数据库访问对象(Connection、Statement)等。
  2. 需要保证产品家族的一致性:
    • 比如确保所有UI组件都是同一风格,或者所有家具都是同一主题。
  3. 系统需要独立于产品的创建、组合和表示:
    • 比如框架或库的设计,希望将对象的创建逻辑与使用逻辑分离。
  4. 需要支持多种产品家族:
    • 比如支持多种数据库(MySQL、Oracle)、多种操作系统(Windows、Mac)、多种主题(现代、古典)等。
  5. 希望通过配置或依赖注入动态切换产品家族:
    • 比如Spring框架中通过配置文件切换具体的Bean实现。
目录
相关文章
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
457 16
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
540 15
|
设计模式 JavaScript Java
【设计模式】【创建型模式】原型模式(Prototype)
一、入门 什么是原型模式? 原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化类。 原型模式的核心是克隆(Clone),即通过复制现有
388 15
|
设计模式 Java Apache
【设计模式】【创建型模式】建造者模式(Builder)
一、入门 什么是建造者模式? 建造者模式(Builder Pattern)是一种创建型设计模式,用于逐步构建复杂对象。 它通过将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。 为什么
982 14
|
设计模式 Java 关系型数据库
设计模式:工厂方法模式(Factory Method)
工厂方法模式是一种创建型设计模式,通过将对象的创建延迟到子类实现解耦。其核心是抽象工厂声明工厂方法返回抽象产品,具体工厂重写该方法返回具体产品实例。适用于动态扩展产品类型、复杂创建逻辑和框架设计等场景,如日志记录器、数据库连接池等。优点包括符合开闭原则、解耦客户端与具体产品;缺点是可能增加类数量和复杂度。典型应用如Java集合框架、Spring BeanFactory等。
|
设计模式 XML Java
设计模式觉醒系列(03)创建型模式的5个设计模式 | 一口气讲全讲透
本文详细介绍了设计模式中的创建型模式,包括建造者模式、原型模式、单例模式、工厂方法模式和抽象工厂模式。创建型模式关注对象的创建过程,隐藏了创建细节,以提高代码的可维护性和可扩展性。通过具体的实战demo和应用场景分析,展示了每种模式的特点和优势。例如,建造者模式适用于复杂对象的分步骤构建;原型模式通过复制对象实现高效复用;单例模式确保全局唯一实例;工厂方法模式和抽象工厂模式则提供了灵活的对象创建机制,支持多类型产品族的生产。这些模式在实际开发中能够简化客户端代码,提升系统灵活性和复用性。
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
478 0
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
655 0
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
393 0
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
1083 11

热门文章

最新文章