Java设计模式 简单工厂、方法工厂、抽象工厂之spring应用

发布时间:2026/7/21 16:29:32
Java设计模式 简单工厂、方法工厂、抽象工厂之spring应用 在Spring框架中工厂模式的应用非常广泛且深入主要体现在‌Bean的实例化方式‌和‌框架内部的核心设计‌两个层面。Spring不仅支持传统的简单工厂、工厂方法和抽象工厂思想还通过特有的FactoryBean接口对工厂模式进行了深度封装和扩展。以下是这三种工厂模式在Spring中的具体应用解析一、简单工厂模式在Spring中的应用简单工厂模式的核心是“一个工厂类根据参数创建不同对象”。在Spring中这主要体现为‌静态工厂方法创建Bean‌。1. 配置方式当我们需要通过某个类的静态方法来获取Bean实例时可以使用class属性指定工厂类factory-method指定静态方法。!-- XML配置示例 --beanidairplaneclasscom.example.factory.AirPlaneFactoryfactory-methodcreateAirPlaneconstructor-argvalueBoeing//bean2. 应用场景‌第三方库集成‌当需要整合一些没有无参构造函数、或者必须通过特定静态工具类获取实例的老旧系统或第三方SDK时。‌简化配置‌对于逻辑简单的对象创建避免编写复杂的Java Config代码。二、工厂方法模式在Spring中的应用工厂方法模式的核心是“定义创建接口让子类决定实例化哪一个类”。在Spring中这体现为‌实例工厂方法创建Bean‌。1. 配置方式与静态工厂不同实例工厂需要先创建工厂Bean本身再通过factory-bean引用该工厂factory-method调用其非静态方法。!-- XML配置示例 --!-- 1. 先创建工厂实例 --beanidairPlaneFactoryclasscom.example.factory.AirPlaneInstanceFactory/!-- 2. 通过工厂实例创建目标Bean --beanidairplane2factory-beanairPlaneFactoryfactory-methodcreateAirPlaneconstructor-argvalueAirbus//bean2. 应用场景‌依赖注入工厂‌当工厂本身也需要依赖其他Spring管理的Bean如数据源、配置信息时必须使用实例工厂因为静态方法无法享受Spring的依赖注入特性。‌动态策略选择‌根据运行时上下文动态决定创建哪种实现类符合开闭原则。三、抽象工厂模式与Spring的深度结合FactoryBean这是Spring对工厂模式最精妙、最核心的应用。Spring提供了org.springframework.beans.factory.FactoryBean接口它不仅仅是一个设计模式的实现更是Spring容器扩展能力的基石。1. 核心原理FactoryBean是一个特殊的Bean它本身是一个工厂用来生产另一个Bean。‌getObject()‌定义生产复杂对象的具体逻辑。‌getObjectType()‌返回生产对象的类型用于Spring的类型匹配和自动装配。‌isSingleton()‌决定生产的对象是单例还是原型。2. Spring内部的智能处理Spring容器在初始化时如果检测到某个Bean实现了FactoryBean接口‌不会直接返回FactoryBean实例‌而是调用其getObject()方法将返回的对象注册到容器中。‌特殊访问机制‌context.getBean(“myBean”)获取的是FactoryBean生产的‌产品对象‌。context.getBean(“myBean”)获取的是‌FactoryBean工厂本身‌通过添加前缀。3. 典型应用场景FactoryBean在Spring生态中无处不在主要用于处理‌复杂对象的创建‌这些对象往往无法通过简单的构造函数或Setter完成初始化‌MyBatis整合‌SqlSessionFactoryBean是典型的FactoryBean它负责解析MyBatis配置文件、构建数据源、创建SqlSessionFactory。我们在Spring中注入的其实是SqlSessionFactory而不是FactoryBean本身。‌AOP代理对象‌Spring AOP生成的代理对象Proxy通常也是通过类似的工厂机制创建的确保代理对象正确包裹目标Bean。‌JNDI查找‌JndiObjectFactoryBean用于从JNDI环境中查找资源如DataSource将复杂的JNDI查找逻辑封装在工厂内部。‌延迟初始化与复杂构建‌当Bean的创建过程涉及网络连接、文件IO或复杂的计算逻辑时使用FactoryBean可以将这些逻辑封装保持配置简洁。四简单工厂模式java代码完整示例简单工厂模式Simple Factory Pattern又称静态工厂方法模式其核心思想是由一个工厂类根据传入的参数动态决定应该创建哪一个产品类的实例。虽然它不属于 GoF 23 种设计模式之一但在实际开发中非常常用能有效解耦客户端与具体产品的依赖。以下是一个完整的、可运行的 Java 代码示例模拟一个‌图形绘制系统‌系统支持绘制圆形、矩形和正方形通过简单工厂模式统一创建图形对象。1. 核心角色定义第一步定义抽象产品Product所有具体图形必须实现的接口或抽象类。/** * 抽象产品图形接口 */publicinterfaceShape{voiddraw();}第二步定义具体产品Concrete Product实现抽象接口的具体图形类。/** * 具体产品圆形 */publicclassCircleimplementsShape{Overridepublicvoiddraw(){System.out.println(Inside Circle::draw() method.);}}/** * 具体产品矩形 */publicclassRectangleimplementsShape{Overridepublicvoiddraw(){System.out.println(Inside Rectangle::draw() method.);}}/** * 具体产品正方形 */publicclassSquareimplementsShape{Overridepublicvoiddraw(){System.out.println(Inside Square::draw() method.);}}第三步定义工厂类Factory这是简单工厂模式的核心包含一个静态方法根据传入的类型标识创建对应的对象。/** * 简单工厂类ShapeFactory * 负责根据类型字符串创建具体的 Shape 对象 */publicclassShapeFactory{// 使用静态方法方便客户端直接调用无需实例化工厂publicstaticShapegetShape(StringshapeType){if(shapeTypenull){returnnull;}// 忽略大小写比较提高健壮性if(shapeType.equalsIgnoreCase(CIRCLE)){returnnewCircle();}elseif(shapeType.equalsIgnoreCase(RECTANGLE)){returnnewRectangle();}elseif(shapeType.equalsIgnoreCase(SQUARE)){returnnewSquare();}returnnull;}}2. 客户端调用Client客户端只需要知道工厂类和抽象产品接口完全不需要知道具体产品类Circle, Rectangle 等的存在。publicclassClient{publicstaticvoidmain(String[]args){// 1. 获取圆形对象并绘制ShapecircleShapeFactory.getShape(CIRCLE);if(circle!null){circle.draw();}// 2. 获取矩形对象并绘制ShaperectangleShapeFactory.getShape(RECTANGLE);if(rectangle!null){rectangle.draw();}// 3. 获取正方形对象并绘制ShapesquareShapeFactory.getShape(SQUARE);if(square!null){square.draw();}// 4. 测试无效输入ShapeunknownShapeFactory.getShape(TRIANGLE);if(unknownnull){System.out.println(Unknown shape type requested.);}}}3. 运行结果InsideCircle::draw()method.InsideRectangle::draw()method.InsideSquare::draw()method.Unknownshape type requested.4. 代码结构解析与优缺点优点‌解耦‌客户端Client不再直接使用 new Circle() 或 new Rectangle()而是依赖 ShapeFactory 和 Shape 接口。如果未来修改了具体产品的构造函数或初始化逻辑只需修改工厂类客户端代码无需变动。‌简化客户端代码‌客户端无需关心对象创建的复杂细节只需传递一个简单的参数即可获取所需对象。‌集中管理‌对象的创建逻辑集中在一个地方便于维护和统一控制例如可以在工厂中加入缓存逻辑实现单例或对象池。缺点‌违反开闭原则OCP‌这是简单工厂模式最大的缺陷。如果需要新增一种图形如三角形 Triangle必须修改 ShapeFactory 类中的 getShape 方法增加新的 if-else 或 switch-case 分支。在大型系统中这会导致工厂类变得非常臃肿且难以维护。‌职责过重‌工厂类承担了所有产品的创建逻辑一旦工厂类出错整个系统的对象创建都会受到影响。5. 适用场景产品种类相对固定不会频繁新增。客户端只关心最终得到的产品对象而不关心其创建过程。创建逻辑比较简单不需要复杂的层级结构。‌提示‌如果产品种类频繁扩展建议升级为‌工厂方法模式‌Factory Method Pattern通过让子类决定实例化哪一个类来符合开闭原则。工厂方法模式的Java完整代码示例工厂方法模式Factory Method Pattern的核心在于‌定义一个创建对象的接口但让子类决定实例化哪一个类‌。它将对象的实例化过程延迟到子类中从而符合“开闭原则”对扩展开放对修改关闭。以下是一个完整的、可运行的 Java 代码示例模拟一个‌日志记录器系统‌系统支持多种日志记录方式如控制台日志、文件日志通过工厂方法模式实现解耦。1. 核心角色定义第一步定义抽象产品Product这是所有具体产品必须实现的接口或抽象类。/** * 抽象产品日志记录器接口 */publicinterfaceLogger{voidlog(Stringmessage);}第二步定义具体产品Concrete Product实现抽象产品的具体类。/** * 具体产品控制台日志记录器 */publicclassConsoleLoggerimplementsLogger{Overridepublicvoidlog(Stringmessage){System.out.println([Console Log]: message);}}/** * 具体产品文件日志记录器 */publicclassFileLoggerimplementsLogger{Overridepublicvoidlog(Stringmessage){// 模拟写入文件操作System.out.println([File Log]: Writing to file - message);}}第三步定义抽象工厂Creator声明工厂方法该方法返回抽象产品类型的对象。/** * 抽象工厂日志工厂接口 * 核心定义创建 Logger 的规范但不指定具体创建哪个 Logger */publicabstractclassLoggerFactory{/** * 工厂方法由子类实现具体的创建逻辑 * return Logger 实例 */publicabstractLoggercreateLogger();/** * 业务方法使用创建出的 Logger 进行日志记录 * 注意这里依赖的是抽象产品 Logger而不是具体实现 */publicvoidwriteLog(Stringmessage){Loggerloggerthis.createLogger();logger.log(message);}}第四步定义具体工厂Concrete Creator重写工厂方法返回具体的产品实例。/** * 具体工厂控制台日志工厂 * 负责创建 ConsoleLogger */publicclassConsoleLoggerFactoryextendsLoggerFactory{OverridepublicLoggercreateLogger(){returnnewConsoleLogger();}}/** * 具体工厂文件日志工厂 * 负责创建 FileLogger */publicclassFileLoggerFactoryextendsLoggerFactory{OverridepublicLoggercreateLogger(){returnnewFileLogger();}}2. 客户端调用Client客户端只依赖抽象工厂和抽象产品完全不知道具体产品的存在。publicclassClient{publicstaticvoidmain(String[]args){System.out.println( 测试控制台日志 );// 1. 创建具体工厂LoggerFactoryconsoleFactorynewConsoleLoggerFactory();// 2. 通过工厂执行业务逻辑内部会自动创建 ConsoleLoggerconsoleFactory.writeLog(系统启动成功);System.out.println(\n 测试文件日志 );// 1. 创建另一个具体工厂LoggerFactoryfileFactorynewFileLoggerFactory();// 2. 通过工厂执行业务逻辑内部会自动创建 FileLoggerfileFactory.writeLog(用户登录异常: ID1001);System.out.println(\n 扩展性演示 );// 如果未来需要增加 DatabaseLogger只需新增 DatabaseLogger 类和 DatabaseLoggerFactory 类// 无需修改现有的 LoggerFactory、ConsoleLoggerFactory 或 Client 代码}}3. 运行结果测试控制台日志[ConsoleLog]:系统启动成功测试文件日志[FileLog]:Writingtofile-用户登录异常:ID1001扩展性演示4. 代码结构解析与优势‌解耦创建与使用‌Client 类中没有任何 new ConsoleLogger() 或 new FileLogger() 的代码。Client 只依赖于 LoggerFactory 和 Logger 这两个抽象层。‌符合开闭原则OCP‌‌扩展‌如果需要新增一种“数据库日志”只需新建 DatabaseLogger 实现 Logger 接口并新建 DatabaseLoggerFactory 继承 LoggerFactory。‌不修改‌原有的 ConsoleLoggerFactory、FileLoggerFactory 以及 Client 代码完全不需要改动。‌单一职责‌每个具体工厂类只负责创建一个特定的产品逻辑清晰避免了简单工厂模式中巨大的 if-else 或 switch-case 判断块。5. 与简单工厂模式的对比特性简单工厂模式工厂方法模式‌工厂结构‌只有一个静态工厂类有一个抽象工厂基类多个具体工厂子类‌新增产品‌需修改工厂类的 if-else 逻辑新增一个具体工厂类无需修改旧代码‌开闭原则‌违反修改了现有代码符合仅扩展新代码‌适用场景‌产品种类少且固定产品种类多且可能频繁扩展这个示例展示了工厂方法模式如何通过‌多态‌和‌继承‌机制将对象创建的复杂性封装在子类中是大型框架如 Spring、JDBC驱动加载中非常常见的设计手法。抽象工厂java代码完整示例抽象工厂模式Abstract Factory Pattern是一种创建型设计模式它提供一个接口或抽象类用于创建‌一系列相关或相互依赖的对象‌而无需指定它们具体的类。以下是一个完整的、可运行的 Java 代码示例模拟一个‌跨平台 UI 组件库‌系统需要同时创建按钮Button和文本框TextField且必须保证同一套界面风格如 Windows 风格或 Mac 风格的一致性。1. 核心角色定义第一步定义抽象产品Abstract Products定义一组相关产品的接口。在这个例子中我们有两种产品按钮和文本框。/** * 抽象产品 A按钮接口 */publicinterfaceButton{voidrender();voidonClick();}/** * 抽象产品 B文本框接口 */publicinterfaceTextField{voidrender();voidinputText(Stringtext);}第二步定义具体产品Concrete Products实现抽象产品接口的具体类分为不同的产品族Windows 族和 Mac 族。// --- Windows 产品族 ---/** * 具体产品 A1Windows 按钮 */publicclassWindowsButtonimplementsButton{Overridepublicvoidrender(){System.out.println(Render a button in Windows style.);}OverridepublicvoidonClick(){System.out.println(Bind Windows click event listener.);}}/** * 具体产品 B1Windows 文本框 */publicclassWindowsTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Render a text field in Windows style.);}OverridepublicvoidinputText(Stringtext){System.out.println(Input text into Windows text field: text);}}// --- Mac 产品族 ---/** * 具体产品 A2Mac 按钮 */publicclassMacButtonimplementsButton{Overridepublicvoidrender(){System.out.println(Render a button in Mac OS style.);}OverridepublicvoidonClick(){System.out.println(Bind Mac OS click event listener.);}}/** * 具体产品 B2Mac 文本框 */publicclassMacTextFieldimplementsTextField{Overridepublicvoidrender(){System.out.println(Render a text field in Mac OS style.);}OverridepublicvoidinputText(Stringtext){System.out.println(Input text into Mac OS text field: text);}}第三步定义抽象工厂Abstract Factory声明一组用于创建不同产品的方法。每个方法对应一种产品类型。/** * 抽象工厂接口 * 声明创建 Button 和 TextField 的方法 */publicinterfaceGUIFactory{ButtoncreateButton();TextFieldcreateTextField();}第四步定义具体工厂Concrete Factories实现抽象工厂接口负责创建特定产品族Windows 或 Mac的所有产品。/** * 具体工厂Windows 工厂 * 负责创建 Windows 风格的一系列组件 */publicclassWindowsFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewWindowsButton();}OverridepublicTextFieldcreateTextField(){returnnewWindowsTextField();}}/** * 具体工厂Mac 工厂 * 负责创建 Mac 风格的一系列组件 */publicclassMacFactoryimplementsGUIFactory{OverridepublicButtoncreateButton(){returnnewMacButton();}OverridepublicTextFieldcreateTextField(){returnnewMacTextField();}}2. 客户端调用Client客户端只依赖抽象工厂和抽象产品接口。通过切换具体的工厂实例可以一键切换整个产品族。publicclassApplication{privateButtonbutton;privateTextFieldtextField;/** * 构造函数接收抽象工厂不关心具体是哪种工厂 */publicApplication(GUIFactoryfactory){this.buttonfactory.createButton();this.textFieldfactory.createTextField();}publicvoidpaint(){button.render();button.onClick();textField.render();textField.inputText(Hello Abstract Factory!);}publicstaticvoidmain(String[]args){System.out.println( 运行在 Windows 环境下 );// 1. 创建 Windows 工厂GUIFactorywindowsFactorynewWindowsFactory();// 2. 将工厂传入应用ApplicationappWindowsnewApplication(windowsFactory);// 3. 执行绘制所有组件都是 Windows 风格appWindows.paint();System.out.println(\n 运行在 Mac 环境下 );// 1. 创建 Mac 工厂GUIFactorymacFactorynewMacFactory();// 2. 将工厂传入应用ApplicationappMacnewApplication(macFactory);// 3. 执行绘制所有组件都是 Mac 风格appMac.paint();}}3. 运行结果运行在Windows环境下Rendera button inWindowsstyle.BindWindowsclick eventlistener.Rendera text field inWindowsstyle.Inputtext intoWindowstext field:HelloAbstractFactory!运行在Mac环境下Rendera button inMacOSstyle.BindMacOSclick eventlistener.Rendera text field inMacOSstyle.Inputtext intoMacOStext field:HelloAbstractFactory!4. 代码结构解析与优势‌产品族一致性‌Application 类中button 和 textField 是由同一个工厂对象创建的。如果使用 WindowsFactory那么得到的必然是 WindowsButton 和 WindowsTextField绝不会出现“Windows 按钮”搭配“Mac 文本框”这种风格不一致的情况。‌符合开闭原则‌‌扩展新系列‌如果未来需要支持 Linux 风格只需新增 LinuxButton、LinuxTextField 和 LinuxFactory无需修改现有的 WindowsFactory、MacFactory 或 Application 代码。‌缺点‌如果需要在产品族中增加一个新的产品类型例如增加一个 Checkbox 复选框则必须修改抽象工厂接口 GUIFactory 以及所有具体工厂类这违反了开闭原则。因此抽象工厂模式适用于‌产品结构稳定但产品族经常切换‌的场景。‌解耦‌客户端代码Application完全不依赖具体的产品类如 WindowsButton只依赖抽象接口。这使得代码更容易测试和维护。5. 与工厂方法模式的对比特性工厂方法模式抽象工厂模式‌关注点‌单个产品的创建一系列相关/依赖产品族的创建‌产品维度‌单一维度如只有 Button多个维度如 Button TextField Checkbox‌实现方式‌通过继承子类重写工厂方法通过组合工厂内部包含多个工厂方法‌适用场景‌只需要创建一个对象且希望解耦创建逻辑需要确保创建的一组对象属于同一系列且风格一致这个示例展示了抽象工厂模式如何通过封装一组工厂方法确保客户端获取到的是一整套协调一致的对象是构建跨平台应用、主题切换系统时的经典选择。四、总结对比模式类型Spring中的体现核心特点适用场景‌简单工厂‌静态工厂方法 (factory-method)通过类的静态方法创建无需实例化工厂创建逻辑简单工厂无状态不依赖其他Bean‌工厂方法‌实例工厂方法 (factory-bean)通过Bean实例的非静态方法创建工厂需要依赖其他Spring Bean或需要状态管理‌抽象工厂/高级应用‌FactoryBean 接口标准化接口Spring容器特殊识别支持复杂构建逻辑创建过程复杂、需要介入容器生命周期、整合第三方框架如MyBatis、Hibernate核心结论‌在日常Spring开发中我们很少手动编写简单的工厂类因为Spring IOC容器本身就是一个巨大的工厂。但在‌整合第三方框架‌或‌创建极其复杂的Bean‌时FactoryBean是Spring提供的最强大、最标准的扩展点它完美诠释了工厂模式在框架设计中的价值‌屏蔽复杂创建细节提供统一的获取接口‌。