从模式到架构:Java 工厂模式的设计哲学与工程化实践

news2025/6/4 10:33:34

一、工厂模式概述

(一)定义与核心思想

工厂模式(Factory Pattern)是软件开发中常用的创建型设计模式,其核心思想是将对象的创建过程封装起来,通过工厂类来统一管理对象的创建逻辑。这种模式分离了对象的创建和使用,使得客户端代码无需关心具体的创建细节,只需通过工厂获取所需对象即可。在 Java 开发中,工厂模式通过接口或抽象类定义产品和工厂的规范,具体实现类负责创建具体的产品实例,从而实现了代码的松耦合和高扩展性。

(二)核心作用与优势

  1. 解耦对象创建与使用:客户端代码与具体的对象创建逻辑分离,只需依赖工厂接口或抽象类,降低了模块间的耦合度。
  2. 符合开闭原则:当需要新增产品类型时,只需添加新的具体产品类和对应的工厂类,无需修改现有代码,提高了系统的可扩展性。
  3. 统一管理创建逻辑:将复杂的对象创建过程集中在工厂类中处理,避免了重复代码,便于维护和修改。
  4. 隐藏具体实现细节:客户端只需要知道产品的抽象接口,无需了解具体实现类的细节,增强了代码的封装性。

(三)核心角色

  1. 抽象产品(Product):定义了产品的公共接口或抽象类,所有具体产品都需要实现该接口或继承该抽象类。
  2. 具体产品(Concrete Product):实现了抽象产品接口,是具体的产品实现类。
  3. 抽象工厂(Factory):定义了创建产品的接口,通常是一个接口或抽象类。
  4. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体的产品实例。

二、简单工厂模式(Simple Factory Pattern)

(一)模式定义与特点

简单工厂模式又称为静态工厂模式,它不属于 23 种经典设计模式之一,但却是工厂模式中最基础的实现方式。简单工厂模式通过一个工厂类来根据传入的参数动态决定创建哪种具体产品实例。其特点是工厂类中包含了必要的逻辑判断,能够根据客户端的需求返回对应的产品实例,但缺点是当新增产品类型时,需要修改工厂类的代码,违反了开闭原则。

(二)结构与实现步骤

1. 结构示意图

plaintext

客户端
  ↓
  ├─ 调用工厂类的静态方法
  ↓
简单工厂类(SimpleFactory)
  ↓
  ├─ 根据参数创建具体产品实例
  ↓
抽象产品(Product)
  ↓
具体产品A(ConcreteProductA)、具体产品B(ConcreteProductB)
2. 实现步骤

(1)定义抽象产品接口或抽象类,声明产品的公共方法。
(2)创建具体产品类,实现抽象产品接口。
(3)设计简单工厂类,提供静态方法,根据传入的参数返回对应的具体产品实例。

(三)代码示例

1. 抽象产品接口

java

public interface Product {
    void display();
}
2. 具体产品类

java

public class ConcreteProductA implements Product {
    @Override
    public void display() {
        System.out.println("这是产品A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void display() {
        System.out.println("这是产品B");
    }
}
3. 简单工厂类

java

public class SimpleFactory {
    public static Product createProduct(String productType) {
        if ("A".equals(productType)) {
            return new ConcreteProductA();
        } else if ("B".equals(productType)) {
            return new ConcreteProductB();
        } else {
            throw new IllegalArgumentException("无效的产品类型");
        }
    }
}
4. 客户端调用

java

public class Client {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.display(); // 输出:这是产品A

        Product productB = SimpleFactory.createProduct("B");
        productB.display(); // 输出:这是产品B
    }
}

(四)优缺点与适用场景

1. 优点
  • 实现简单,客户端无需知道具体产品的创建细节。
  • 集中管理对象的创建逻辑,便于维护。
2. 缺点
  • 工厂类职责过重,违反了单一职责原则。
  • 新增产品类型时需要修改工厂类代码,违反开闭原则。
3. 适用场景
  • 产品类型较少,且后续扩展需求不大的场景。
  • 简单的业务逻辑中,需要将对象创建逻辑集中管理的情况。

三、工厂方法模式(Factory Method Pattern)

(一)模式定义与核心思想

工厂方法模式是 23 种经典设计模式之一,它定义了一个创建产品对象的接口,但由具体工厂类决定创建哪种具体产品实例。工厂方法模式将简单工厂模式中集中的创建逻辑分散到各个具体工厂类中,每个具体工厂类负责创建一种具体产品,从而克服了简单工厂模式违反开闭原则的缺点。

(二)结构与实现步骤

1. 结构示意图

plaintext

客户端
  ↓
  ├─ 调用抽象工厂接口
  ↓
抽象工厂(Factory)
  ↓
  ├─ 声明创建产品的抽象方法
  ↓
具体工厂A(ConcreteFactoryA)、具体工厂B(ConcreteFactoryB)
  ↓
  ├─ 实现创建具体产品的方法
  ↓
抽象产品(Product)
  ↓
具体产品A(ConcreteProductA)、具体产品B(ConcreteProductB)
2. 实现步骤

(1)定义抽象产品接口,声明产品的公共方法。
(2)创建具体产品类,实现抽象产品接口。
(3)定义抽象工厂接口,声明创建产品的抽象方法。
(4)创建具体工厂类,实现抽象工厂接口,具体工厂类负责创建对应的具体产品实例。

(三)代码示例

1. 抽象产品接口(同简单工厂模式)

java

public interface Product {
    void display();
}
2. 具体产品类(同简单工厂模式)

java

public class ConcreteProductA implements Product {
    @Override
    public void display() {
        System.out.println("这是产品A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void display() {
        System.out.println("这是产品B");
    }
}
3. 抽象工厂接口

java

public interface Factory {
    Product createProduct();
}
4. 具体工厂类

java

public class ConcreteFactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}
5. 客户端调用

java

public class Client {
    public static void main(String[] args) {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.display(); // 输出:这是产品A

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.display(); // 输出:这是产品B
    }
}

(四)优缺点与适用场景

1. 优点
  • 符合开闭原则,新增产品类型时只需添加新的具体产品类和具体工厂类,无需修改现有代码。
  • 每个具体工厂类负责创建一种产品,符合单一职责原则。
  • 客户端只依赖抽象接口,降低了与具体实现类的耦合度。
2. 缺点
  • 当产品类型较多时,会导致具体工厂类的数量增加,系统复杂度上升。
  • 对于简单的对象创建场景,可能会引入过多的类,增加代码的复杂性。
3. 适用场景
  • 当系统需要灵活地创建不同类型的产品,且新增产品类型频繁时。
  • 希望将对象的创建逻辑与使用逻辑分离,提高代码的可扩展性和维护性。
  • 客户端只需要知道产品的抽象接口,不需要了解具体实现类的情况。

四、抽象工厂模式(Abstract Factory Pattern)

(一)模式定义与核心思想

抽象工厂模式是工厂方法模式的扩展,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式用于创建属于不同产品族的产品对象,每个产品族中的产品具有某种共同的特性或功能,例如不同操作系统下的界面组件(Windows 和 Linux 下的按钮、文本框等)。

(二)核心概念

  1. 产品族:指位于不同产品等级结构中,功能相关联的产品组成的家族。例如,Windows 系统下的按钮、文本框属于一个产品族,Linux 系统下的按钮、文本框属于另一个产品族。
  2. 产品等级结构:指产品的继承结构,例如按钮作为一个抽象产品,有 Windows 按钮和 Linux 按钮两个具体产品,形成一个产品等级结构。

(三)结构与实现步骤

1. 结构示意图

plaintext

客户端
  ↓
  ├─ 调用抽象工厂接口创建产品族
  ↓
抽象工厂(AbstractFactory)
  ↓
  ├─ 声明创建各产品等级结构中产品的方法
  ↓
具体工厂A(ConcreteFactoryA)、具体工厂B(ConcreteFactoryB)
  ↓
  ├─ 实现创建具体产品族的方法
  ↓
抽象产品A(AbstractProductA)、抽象产品B(AbstractProductB)
  ↓
具体产品A1(ConcreteProductA1)、具体产品A2(ConcreteProductA2)
具体产品B1(ConcreteProductB1)、具体产品B2(ConcreteProductB2)
2. 实现步骤

(1)定义多个抽象产品接口,分别代表不同的产品等级结构。
(2)创建具体产品类,实现对应的抽象产品接口。
(3)定义抽象工厂接口,声明创建各个抽象产品的方法。
(4)创建具体工厂类,实现抽象工厂接口,具体工厂类负责创建属于同一产品族的多个产品实例。

(四)代码示例

1. 抽象产品接口(产品等级结构 1:按钮)

java

public interface Button {
    void display();
}

public class WindowsButton implements Button {
    @Override
    public void display() {
        System.out.println("Windows按钮");
    }
}

public class LinuxButton implements Button {
    @Override
    public void display() {
        System.out.println("Linux按钮");
    }
}
2. 抽象产品接口(产品等级结构 2:文本框)

java

public interface TextBox {
    void display();
}

public class WindowsTextBox implements TextBox {
    @Override
    public void display() {
        System.out.println("Windows文本框");
    }
}

public class LinuxTextBox implements TextBox {
    @Override
    public void display() {
        System.out.println("Linux文本框");
    }
}
3. 抽象工厂接口

java

public interface GUIFactory {
    Button createButton();
    TextBox createTextBox();
}
4. 具体工厂类(Windows 工厂)

java

public class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextBox createTextBox() {
        return new WindowsTextBox();
    }
}
5. 具体工厂类(Linux 工厂)

java

public class LinuxFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new LinuxButton();
    }

    @Override
    public TextBox createTextBox() {
        return new LinuxTextBox();
    }
}
6. 客户端调用

java

public class Client {
    public static void main(String[] args) {
        GUIFactory factory = new WindowsFactory();
        Button button = factory.createButton();
        TextBox textBox = factory.createTextBox();
        button.display(); // 输出:Windows按钮
        textBox.display(); // 输出:Windows文本框

        factory = new LinuxFactory();
        button = factory.createButton();
        textBox = factory.createTextBox();
        button.display(); // 输出:Linux按钮
        textBox.display(); // 输出:Linux文本框
    }
}

(五)优缺点与适用场景

1. 优点
  • 可以创建多个产品族的产品,满足复杂的对象创建需求。
  • 客户端只依赖抽象接口,无需了解具体产品的创建细节,提高了代码的可维护性和扩展性。
  • 确保同一产品族中的产品之间的兼容性,例如 Windows 工厂创建的按钮和文本框一定是相互兼容的。
2. 缺点
  • 当需要新增一个产品等级结构时,需要修改抽象工厂接口和所有具体工厂类,违反了开闭原则。
  • 系统复杂度较高,适用于产品族较多且稳定的场景。
3. 适用场景
  • 系统需要创建多个相关或相互依赖的对象族,例如不同操作系统下的界面组件。
  • 产品族中的产品种类固定,且不会频繁新增产品等级结构的场景。
  • 需要确保产品族中的产品之间相互兼容,避免客户端直接创建具体产品类的情况。

五、三种工厂模式的对比与选择

(一)模式对比表

特征简单工厂模式工厂方法模式抽象工厂模式
工厂类数量一个工厂类多个具体工厂类多个具体工厂类
产品等级结构单个产品等级结构单个产品等级结构多个产品等级结构
产品族不支持不支持支持
开闭原则违反符合部分符合(新增产品族符合,新增产品等级结构违反)
复杂度简单中等复杂

(二)选择策略

  1. 简单工厂模式:适用于产品类型较少、逻辑简单且后续扩展需求不大的场景,可快速实现对象的集中创建。
  2. 工厂方法模式:当系统需要灵活地新增产品类型,且每个产品类型的创建逻辑相对独立时,优先选择工厂方法模式,它符合开闭原则,易于扩展。
  3. 抽象工厂模式:当系统需要处理多个产品族,且每个产品族包含多个相关产品时,抽象工厂模式能够高效地管理产品族的创建,确保产品之间的兼容性。

六、工厂模式与设计原则

(一)开闭原则

工厂模式通过抽象接口和具体实现的分离,使得新增产品类型或产品族时无需修改现有代码,只需添加新的具体类,符合开闭原则的 “对扩展开放,对修改关闭” 要求。

(二)单一职责原则

工厂方法模式和抽象工厂模式中,每个具体工厂类只负责创建一种或一类产品,符合单一职责原则,而简单工厂模式的工厂类职责较为集中,可能违反该原则。

(三)依赖倒置原则

工厂模式中,客户端依赖抽象产品接口和抽象工厂接口,而不是具体实现类,遵循了依赖倒置原则,降低了客户端与具体实现的耦合度。

(四)里氏替换原则

具体产品类必须实现抽象产品接口的所有方法,具体工厂类必须实现抽象工厂接口的所有方法,确保了子类可以无缝替换父类,符合里氏替换原则。

七、工厂模式在 Java 中的应用场景

(一)Java 集合框架

在 Java 集合框架中,Collection接口是抽象产品,ArrayListLinkedList等是具体产品,而它们的创建过程虽然没有显式的工厂类,但通过构造方法或工厂方法(如Arrays.asList())实现了对象的创建,体现了工厂模式的思想。

(二)Spring 框架

Spring 框架中的 BeanFactory 和 ApplicationContext 就是工厂模式的典型应用。BeanFactory 作为抽象工厂,负责创建各种 Bean 对象,而具体的 Bean 创建逻辑由具体的工厂类(如 DefaultListableBeanFactory)实现。通过配置文件或注解,客户端可以轻松获取所需的 Bean 实例,无需关心对象的创建细节。

(三)JDBC 驱动

JDBC 中使用DriverManager获取数据库连接的过程也应用了工厂模式。DriverManager作为工厂类,根据不同的数据库 URL 创建对应的数据库连接(Connection对象),客户端只需通过统一的接口操作数据库,无需了解具体数据库驱动的创建细节。

八、总结与最佳实践

(一)模式价值

工厂模式是面向对象设计中处理对象创建的重要模式,它通过封装对象创建逻辑,提高了代码的可维护性、可扩展性和可复用性。无论是简单工厂模式的快速实现,还是工厂方法模式和抽象工厂模式的灵活扩展,都为软件开发提供了有效的解决方案。

(二)最佳实践

  1. 优先使用组合而非继承:在设计工厂类时,尽量通过组合的方式复用创建逻辑,避免过度使用继承导致系统复杂度增加。
  2. 明确抽象层次:合理定义抽象产品接口和抽象工厂接口,确保接口的稳定性和扩展性,避免频繁修改接口。
  3. 结合其他模式:工厂模式可以与单例模式、原型模式等结合使用,例如将工厂类设计为单例,确保全局唯一的创建点。
  4. 测试工厂逻辑:由于工厂类负责对象的创建,需要对其进行充分的测试,确保返回的产品实例符合预期,尤其是在处理复杂创建逻辑时。

(三)未来趋势

随着软件开发的复杂化和模块化需求的增加,工厂模式在微服务、框架设计等领域的应用将更加广泛。结合 Java 8 的函数式接口和 Lambda 表达式,工厂模式的实现方式也在不断演进,例如使用Supplier接口简化对象创建过程,提高代码的简洁性和灵活性。

总之,掌握工厂模式的核心思想和不同实现方式,能够帮助开发者在实际项目中更好地设计对象创建逻辑,提升系统的可维护性和扩展性,是 Java 开发中不可或缺的重要设计模式之一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2396449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker问题记录

docker pull镜像: 即使配置了镜像源也还是走的国外的镜像源: 解决办法:在pull镜像的时候强制走自己的镜像 比如:拉取rabbitmq,强制使用"https://docker.m.daocloud.io"这个镜像 docker pull docker.m.da…

设计模式——代理设计模式(结构型)

摘要 本文详细介绍了代理设计模式,包括其定义、结构组成、实现方式、适用场景及实战示例。代理设计模式是一种结构型设计模式,通过代理对象控制对目标对象的访问,可增强功能或延迟加载等。文中通过类图、时序图、静态代理、JDK动态代理、CGL…

从“固定“到“流动“:移动充电如何重塑用户体验?

在传统充电模式中,"固定"不仅是技术的特征,更成为用户行为的枷锁——人们需要规划行程、寻找插座、等待电量填满,这种被动适配正在被移动充电技术颠覆。当充电设备从墙面解放,化身可携带的能源胶囊,甚至嵌入…

玩客云 OEC/OECT 笔记(1) 拆机刷入Armbian固件

目录 玩客云 OEC/OECT 笔记(1) 拆机刷入Armbian固件玩客云 OEC/OECT 笔记(2) 运行RKNN程序 外观 内部 PCB正面 PCB背面 PCB背面 RK3566 1Gbps PHY 配置 OEC 和 OECT(OEC-turbo) 都是基于瑞芯微 RK3566/RK3568 的网络盒子, 没有HDMI输入输出. 硬件上 OEC 和 OECT…

GIS数据类型综合解析

GIS数据类型综合解析 目录 GIS数据类型综合解析1. 总体介绍2. GIS数据类型分类与对比2.1 主要数据类型对比表 3. 详细解析与扩展内容3.1 矢量数据(Vector Data)3.2 栅格数据(Raster Data)3.3 属性数据(Attribute Data&…

Prometheus + Grafana 监控常用服务

一、引言 Prometheus监控常见服务的原理主要包括服务暴露指标和Prometheus抓取指标。一方面,被监控服务通过自身提供的监控接口或借助Exporter将服务的性能指标等数据以HTTP协议的方式暴露出来;另一方面,Prometheus根据配置好的采集任务&…

6月1日星期日今日早报简报微语报早读

6月1日星期日,农历五月初六,早报#微语早读。 1、10个省份城镇化率超70%,广东城镇人口超9700万; 2、长沙居民起诉太平财险不赔“新冠险”,立案878天后获胜判; 3、海口:全市范围内禁止投放互联…

如何在 Ubuntu 24.04 服务器上安装 Apache Solr

Apache Solr 是一个免费、开源的搜索平台,广泛应用于实时索引。其强大的可扩展性和容错能力使其在高流量互联网场景下表现优异。 Solr 基于 Java 开发,提供了分布式索引、复制、负载均衡及自动故障转移和恢复等功能。 本教程将指导您如何在 Ubuntu 24.…

unity编辑器扩展dll形式展示

1.背景:最近搞工程迁移发现一旦c#报错就会导致编辑器菜单没法使用,做了一些尝试发现使用dll的方式会是不错的选择。当然有些工具还是建议用外部的c#工程来写比如winform. 2.遇到的问题:我记得之前2017年左右的时候做一个unity的dll工程并不需…

vscode中launch.json、tasks.json的作用及实例

文章目录 launch.json是什么作用多环境调试简单实例进阶使用核心配置项解析调试第三方程序 launch.json是什么 顾名思义:它是在.vscode文件夹下的launch.json,所以是vscode启动调试的配置文件。总结:通过定义调试参数、环境变量和启动方式&a…

VScode编译调试debug,gpu的cuda程序,Nsight

进行下面操作的前提是,我们的环境已经能跑简单的CUDA程序了。 一、安装Nsight 二、创建launch.json文件 {"version": "0.2.0","configurations": [{"name": "CUDA C: Launch","type": "cuda-gdb…

中企出海大会|打造全球化云计算一张网,云网络助力中企出海和AI创新

全球化是阿里云的长期战略,未来阿里云将持续加大云和 AI 基础设施建设投入。首先是加速打造全球化的云计算网络,一张具备 AI技术服务能力和全球竞争力的云计算网络是阿里云的长期目标。 —— 阿里巴巴集团 CEO、阿里云智能集团董事长兼 CEO 吴泳铭 5 月 …

防范DDoS攻击,服务器稳定性崩溃的根源与高效防御对策

DDoS攻击(分布式拒绝服务攻击)已成为危害服务器稳定性和业务连续性的主要因素之一。本文将深入探讨为什么服务器一遇到DDoS攻击就崩溃,以及如何从根本上实现有效防御和应对这一威胁,帮助企业提升网络安全水平。 具体内容如下&…

深入理解 SELinux:通过 Nginx 和 SSH 服务配置实践安全上下文与端口策略

目录 一、引言 二、实验环境说明 三、实验 1:Nginx 服务安全上下文配置 3.1 实验目标 3.2 操作步骤 1. 开启 SELinux 并重启系统 2. 安装 Nginx 并创建自定义目录 3. 配置 Nginx 指向自定义目录 4. 分析 SELinux 上下文冲突 5. 修改上下文为合法类型 6. 验…

C++ —— STL容器——string类

1. 前言 本篇博客将会介绍 string 中的一些常用的函数,在使用 string 中的函数时,需要加上头文件 string。 2. string 中的常见成员函数 2.1 初始化函数 string 类中的常用的初始化函数有以下几种: 1. string() …

用JS实现植物大战僵尸(前端作业)

1. 先搭架子 整体效果&#xff1a; 点击开始后进入主场景 左侧是植物卡片 右上角是游戏的开始和暂停键 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…

Electron-vite【实战】MD 编辑器 -- 文件列表(含右键快捷菜单,重命名文件,删除本地文件,打开本地目录等)

最终效果 页面 src/renderer/src/App.vue <div class"dirPanel"><div class"panelTitle">文件列表</div><div class"searchFileBox"><Icon class"searchFileInputIcon" icon"material-symbols-light:…

华为云Flexus+DeepSeek征文|华为云Flexus云服务器X实例上部署Dify:打造高效的开源大语言模型应用开发平台

目录 前言 1 Dify与华为云部署概述 1.1 什么是 Dify 1.2 华为云与 Flexus 云服务器的优势 2 云服务器部署 Dify 的步骤详解 2.1 模板选择 2.2 参数配置 2.3 资源栈设置 2.4 确认部署信息并执行 3 部署成功后的操作与平台使用指南 3.1 访问平台 3.2 设置管理员账号 …

高密爆炸警钟长鸣:AI为化工安全戴上“智能护盾”

一、高密爆炸&#xff1a;一声巨响&#xff0c;撕开化工安全“伤疤” 2025年5月27日&#xff0c;山东高密友道化学有限公司的车间爆炸声&#xff0c;像一把利刃划破了化工行业的平静。剧烈的冲击波将车间夷为平地&#xff0c;黑色蘑菇云腾空而起&#xff0c;刺鼻的化学气味弥漫…

机器人学基础——正运动学(理论推导及c++实现)

机器人正运动学 机器人正运动学一般是指从机器人的关节位置到基于参考坐标系下末端执行器的位置。 平移变换和旋转变换 平移变换 假设我们有两个坐标系A和B&#xff0c;坐标系A与B的方位相同&#xff0c;xyz轴的指向都是一致的&#xff0c;即没有旋转变换。有一点p&#xf…