Java设计模式之工厂模式详细讲解和案例示范

news2024/9/20 8:04:47

在Java的设计模式中,工厂模式(Factory Pattern)是最常见和最有用的一种创建型模式。工厂模式的核心思想是将对象的创建与使用分离,从而提供了一种灵活的方式来创建不同类型的对象。这种模式尤其适用于复杂对象的创建过程,并且可以很好地应对对象类型的变化。本文将详细讲解工厂模式,结合电商交易系统中的实际应用场景,讨论常见问题和解决方案。

工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,但不向客户端暴露具体的创建逻辑。工厂模式有几种常见的变体,包括简单工厂模式、工厂方法模式和抽象工厂模式。每种变体都在不同的场景下提供了特定的优点。

1. 简单工厂模式

1.1 概述

简单工厂模式(Simple Factory Pattern)又称为静态工厂方法(Static Factory Method),它通过一个工厂类来负责创建具体类的实例。客户端不需要关心对象的具体创建过程,只需通过工厂类来获取对象。

1.2 电商交易系统中的示例

在一个电商交易系统中,我们可能需要处理不同类型的订单,比如普通订单(Regular Order)、会员订单(Member Order)和促销订单(Promotion Order)。我们可以使用简单工厂模式来创建这些订单对象。

1.2.1 代码示例
// 抽象订单类
public interface Order {
    void processOrder();
}

// 普通订单实现
public class RegularOrder implements Order {
    public void processOrder() {
        System.out.println("Processing regular order");
    }
}

// 会员订单实现
public class MemberOrder implements Order {
    public void processOrder() {
        System.out.println("Processing member order");
    }
}

// 促销订单实现
public class PromotionOrder implements Order {
    public void processOrder() {
        System.out.println("Processing promotion order");
    }
}

// 简单工厂类
public class OrderFactory {
    public static Order createOrder(String type) {
        if (type.equals("REGULAR")) {
            return new RegularOrder();
        } else if (type.equals("MEMBER")) {
            return new MemberOrder();
        } else if (type.equals("PROMOTION")) {
            return new PromotionOrder();
        } else {
            throw new IllegalArgumentException("Unknown order type");
        }
    }
}

// 客户端代码
public class ECommerceApp {
    public static void main(String[] args) {
        Order order = OrderFactory.createOrder("MEMBER");
        order.processOrder();
    }
}
1.2.2 类图

在这里插入图片描述

1.3 优缺点
  • 优点
    • 简化了客户端代码,将对象创建逻辑集中到一个地方。
    • 可以很方便地增加新的产品,只需修改工厂类。
  • 缺点
    • 工厂类集中了所有产品的创建逻辑,可能会变得复杂。
    • 当需要增加新类型的订单时,必须修改工厂类,违背了开闭原则(Open/Closed Principle)。

2. 工厂方法模式

2.1 概述

工厂方法模式(Factory Method Pattern)是工厂模式的一种演进。它将对象的创建延迟到子类中,通过定义一个接口或抽象类来实现具体的对象创建。每个子类负责创建特定类型的对象。

2.2 电商交易系统中的示例

在电商交易系统中,我们可以通过工厂方法模式为不同类型的订单创建不同的工厂类,每个工厂类负责创建一种具体的订单类型。

2.2.1 代码示例
// 抽象工厂类
public abstract class OrderFactory {
    public abstract Order createOrder();
}

// 普通订单工厂
public class RegularOrderFactory extends OrderFactory {
    public Order createOrder() {
        return new RegularOrder();
    }
}

// 会员订单工厂
public class MemberOrderFactory extends OrderFactory {
    public Order createOrder() {
        return new MemberOrder();
    }
}

// 促销订单工厂
public class PromotionOrderFactory extends OrderFactory {
    public Order createOrder() {
        return new PromotionOrder();
    }
}

// 客户端代码
public class ECommerceApp {
    public static void main(String[] args) {
        OrderFactory factory = new MemberOrderFactory();
        Order order = factory.createOrder();
        order.processOrder();
    }
}
2.2.2 类图

在这里插入图片描述

2.3 优缺点
  • 优点
    • 遵循开闭原则,新增产品时只需增加新的工厂子类,无需修改已有代码。
    • 客户端代码依赖于抽象工厂,而不是具体产品,减少了耦合。
  • 缺点
    • 需要为每个产品都创建一个工厂类,增加了系统的复杂性。

3. 抽象工厂模式

3.1 概述

抽象工厂模式(Abstract Factory Pattern)是工厂模式中最为复杂的一种。它提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂模式通常用于创建一组相关的产品。

3.2 电商交易系统中的示例

在电商交易系统中,我们可能需要同时创建订单对象和支付对象。可以使用抽象工厂模式来创建这些相关的对象,例如创建会员订单和对应的会员支付服务。

3.2.1 代码示例
// 抽象订单类
public interface Order {
    void processOrder();
}

// 抽象支付类
public interface Payment {
    void processPayment();
}

// 普通订单类
public class RegularOrder implements Order {
    public void processOrder() {
        System.out.println("Processing regular order");
    }
}

// 普通支付类
public class RegularPayment implements Payment {
    public void processPayment() {
        System.out.println("Processing regular payment");
    }
}

// 会员订单类
public class MemberOrder implements Order {
    public void processOrder() {
        System.out.println("Processing member order");
    }
}

// 会员支付类
public class MemberPayment implements Payment {
    public void processPayment() {
        System.out.println("Processing member payment");
    }
}

// 抽象工厂类
public interface ECommerceFactory {
    Order createOrder();
    Payment createPayment();
}

// 普通工厂类
public class RegularECommerceFactory implements ECommerceFactory {
    public Order createOrder() {
        return new RegularOrder();
    }

    public Payment createPayment() {
        return new RegularPayment();
    }
}

// 会员工厂类
public class MemberECommerceFactory implements ECommerceFactory {
    public Order createOrder() {
        return new MemberOrder();
    }

    public Payment createPayment() {
        return new MemberPayment();
    }
}

// 客户端代码
public class ECommerceApp {
    public static void main(String[] args) {
        ECommerceFactory factory = new MemberECommerceFactory();
        Order order = factory.createOrder();
        Payment payment = factory.createPayment();

        order.processOrder();
        payment.processPayment();
    }
}
3.2.2 类图

在这里插入图片描述

3.3 优缺点
  • 优点
    • 抽象工厂模式提供了一个创建相关对象家族的接口,确保这些对象的组合一致性。
    • 客户端代码依赖于抽象工厂,而不是具体产品类,扩展性强。
  • 缺点
    • 如果需要增加新的产品家族,可能需要修改抽象工厂接口以及所有的工厂实现类,增加了维护成本。

4. 工厂模式在开源框架中的应用

工厂模式在Java的开源框架中有广泛的应用。它们利用工厂模式的灵活性和扩展性,简化了对象的创建过程,同时提高了代码的可维护性和可读性。以下是工厂模式在几个常见开源框架中的详细应用分析。

4.1 Spring框架中的工厂模式

Spring框架是Java生态系统中最流行的开源框架之一,它在依赖注入(Dependency Injection)和面向切面编程(Aspect-Oriented Programming)中大量使用了工厂模式。Spring中的工厂模式主要体现在BeanFactoryApplicationContext这两个核心接口中。

4.1.1 BeanFactory

在Spring中,BeanFactory是一个顶层接口,定义了一个管理Bean的容器。BeanFactory通过工厂模式为应用程序提供各种Bean实例的创建和管理功能。

代码示例
// 配置文件:beans.xml
<beans>
    <bean id="orderService" class="com.example.OrderService"/>
    <bean id="paymentService" class="com.example.PaymentService"/>
</beans>

// BeanFactory示例
public class SpringFactoryExample {
    public static void main(String[] args) {
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
        
        // 使用工厂获取Bean实例
        OrderService orderService = (OrderService) factory.getBean("orderService");
        orderService.processOrder();
    }
}

在这个示例中,BeanFactory根据配置文件beans.xml的定义,使用工厂模式来创建并管理OrderServicePaymentService的实例。客户端只需通过getBean()方法获取Bean实例,而不需关心其创建逻辑。

4.1.2 ApplicationContext

ApplicationContext是Spring框架中BeanFactory的扩展接口,提供了更强大的功能,例如国际化支持、事件传播、声明式事务管理等。它也是基于工厂模式来管理和创建Bean的。

代码示例
// ApplicationContext示例
public class SpringContextExample {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        // 使用工厂获取Bean实例
        PaymentService paymentService = (PaymentService) context.getBean("paymentService");
        paymentService.processPayment(100.0);
    }
}

在这个示例中,ApplicationContext提供了比BeanFactory更高级的功能,同时仍然使用工厂模式来管理和创建Bean实例。通过使用ApplicationContext,开发者可以轻松地管理应用程序的依赖关系,并将对象创建与应用逻辑分离。

4.1.3 优势
  • 解耦对象创建与使用:Spring的BeanFactoryApplicationContext通过工厂模式将对象的创建和使用分离,从而实现了松耦合的设计。
  • 配置灵活:开发者可以通过XML或Java注解配置Bean的创建方式,使得应用程序的配置更加灵活。
  • 支持多种对象创建方式:Spring支持单例、原型、工厂方法等多种对象创建方式,极大地提高了框架的适应性。

4.2 Hibernate中的工厂模式

Hibernate是一个广泛使用的Java持久化框架,它利用工厂模式来创建和管理数据库会话(Session)对象。Hibernate中的SessionFactory是工厂模式的一个典型应用。

4.2.1 SessionFactory

SessionFactory是Hibernate框架中用来创建Session对象的工厂类。Session是一个代表与数据库交互的接口,通过SessionFactory可以创建出多个Session实例。

代码示例
// Hibernate配置文件:hibernate.cfg.xml
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">password</property>
        <mapping class="com.example.Order"/>
    </session-factory>
</hibernate-configuration>

// Hibernate工厂模式示例
public class HibernateFactoryExample {
    public static void main(String[] args) {
        // 创建SessionFactory
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        
        // 使用工厂创建Session
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        
        // 操作数据库
        Order order = new Order();
        order.setOrderNumber("12345");
        session.save(order);
        
        session.getTransaction().commit();
        session.close();
    }
}

在这个示例中,SessionFactory通过读取配置文件hibernate.cfg.xml的内容,创建并管理Session对象。客户端通过工厂获取Session实例,并使用它来执行数据库操作。

4.2.2 优势
  • 管理数据库连接SessionFactory通过工厂模式统一管理数据库连接的创建和释放,避免了手动管理数据库连接的复杂性。
  • 提高性能SessionFactory是线程安全的,可以被多个线程共享,这样避免了频繁创建SessionFactory实例的开销。
  • 支持多种数据库:通过配置文件,SessionFactory可以适配不同的数据库类型,增强了Hibernate的灵活性。

4.3 Apache Commons Logging中的工厂模式

Apache Commons Logging是一个通用的日志记录框架,广泛应用于许多Java开源项目中。该框架使用工厂模式来创建和管理日志记录器(Logger)实例。

4.3.1 LogFactory

LogFactory是Apache Commons Logging中的核心工厂类,它负责创建和管理Log接口的具体实现。不同的日志实现(如Log4j、JDK Logging等)可以通过工厂模式进行无缝切换。

代码示例
// Apache Commons Logging示例
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LoggingFactoryExample {
    private static final Log log = LogFactory.getLog(LoggingFactoryExample.class);

    public static void main(String[] args) {
        log.info("This is an info message");
        log.error("This is an error message");
    }
}

在这个示例中,LogFactory通过工厂模式创建Log实例,开发者可以通过LogFactory.getLog()方法获取具体的日志记录器对象。LogFactory根据配置自动选择合适的日志实现,如Log4j或JDK Logging。

4.3.2 优势
  • 兼容性LogFactory通过工厂模式实现了对多种日志框架的支持,使得Apache Commons Logging成为一个通用的日志接口。
  • 灵活性:开发者可以通过配置文件轻松切换不同的日志实现,而不需要修改代码中的任何日志记录逻辑。
  • 统一接口:通过工厂模式,Apache Commons Logging为各种日志实现提供了统一的接口,简化了日志管理的复杂性。

5. 总结

工厂模式在Java的开源框架中得到了广泛的应用,其主要优势在于解耦对象的创建和使用、提供统一的接口和增强代码的灵活性。Spring、Hibernate和Apache Commons Logging等流行的开源框架都利用工厂模式提高了代码的可维护性和可扩展性。

通过对这些框架中工厂模式的详细分析,我们可以更深入地理解工厂模式在实际项目中的应用,并在自己的项目中更好地应用这一设计模式。

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

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

相关文章

HTTrack镜像网站实践

目录 前言 Windows下使用HTTrack HTTrack安装 HTTrack使用 Kali linux下使用HTTrack HTTrack安装 HTTrack使用 前言 在特殊时期&#xff0c;不想把真实的网站页面展示给用户&#xff0c;但又不能关停。此刻&#xff0c;可以用镜像网站替换真实网站&#xff0c;降低安全风…

Golang | Leetcode Golang题解之第378题有序矩阵中第K小的元素

题目&#xff1a; 题解&#xff1a; func kthSmallest(matrix [][]int, k int) int {n : len(matrix)left, right : matrix[0][0], matrix[n-1][n-1]for left < right {mid : left (right - left) / 2if check(matrix, mid, k, n) {right mid} else {left mid 1}}retur…

52.给定一个整数 n,实现一个算法返回 n 皇后不同的解决方案的数量

52. N-Queens II 题目 n皇后问题是指将n个皇后放置在一个nn的棋盘上,使得任意两个皇后不在同一行、同一列或同一对角线上。 给定一个整数 n,返回 n 皇后问题不同的解法数量。 示例: 输入: 4 输出: 2 解释: 4皇后问题有如下两个不同的解法: [ [“.Q…”, // 解法 1 “……

LabVIEW反编译与源程序加密破解

最近&#xff0c;不少粉丝咨询如何将生成的 LabVIEW 可执行程序反编译&#xff0c;所以写了这篇文章来详细探讨这个话题。反编译问题引起了广泛的关注&#xff0c;许多开发者希望能够从现有的可执行文件中提取源代码&#xff0c;以便进行修改或重新利用。然而&#xff0c;反编译…

Java基础:什么是多态

什么是多态 多态是面向对象的三大特性之一&#xff08;另外两个是封装和继承&#xff09;&#xff0c;指的是同一个方法能执行不同的行为&#xff0c;在代码上的体现是&#xff1a;声明为父类的对象&#xff0c;可以被不同的实现类赋值&#xff0c;其中实现类必须继承或者实现…

OpenCV图像拼接多频段融合源码重构

OpenCV图像拼接多频段融合源码重构 图像拼接是计算机视觉中的一个常见问题&#xff0c;OpenCV提供了十分完善的算法类库。作者使用OpenCV4.6.0进行图像拼接&#xff0c;其提供了包括曝光补偿、最佳缝合线检测以及多频段融合等图像拼接常用算法&#xff0c;测试发现多频段融合算…

uni-app - - - - - 自定义tabbar

uni-app - - - - - 自定义tabbar 1. 创建页面2. pages.json3. 自定义tabbar4. 隐藏原生tabbar5. 全局注册组件6. 页面使用7. 效果图展示 1. 创建页面 2. pages.json 配置tabbar {"tabBar": {"list": [{"pagePath": "pages/ballroom/ballr…

认知杂谈25

今天分享 有人说的一段争议性的话 I I 《拖延症&#xff0c;谁都有过》 嘿&#xff0c;朋友们&#xff01;咱都来说说&#xff0c;拖延症这玩意儿&#xff0c;好多人都被它给缠上啦。你看哈&#xff0c;本来计划得好好的&#xff0c;今天要把房间收拾得干干净净&#xff0c;可…

SSH弱口令爆破服务器

一、实验背景 1、概述 使用kali的hydra进行ssh弱口令爆破&#xff0c;获得服务器的用户名和口令&#xff0c;通过 ssh远程登录服务器。 2、实验环境 kali攻击机&#xff1a;192.168.1.107 centos服务器&#xff1a;192.168.1.105 二、前置知识 1、centos设置用户并设置弱…

软件设计原则之接口隔离原则

接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09;是面向对象设计中的一个重要原则&#xff0c;它属于SOLID原则之一。这个原则强调客户端&#xff08;即接口的调用者&#xff09;不应该被迫依赖于它们不使用的方法。换句话说&#xff0c;一个类对另一…

【区块链 + 司法存证】数据存证区块链服务开放平台 | FISCO BCOS应用案例

大数据时代&#xff0c;数据参与社会生产过程&#xff0c;实现价值增值&#xff0c;是一种新型生产要素。数据产品具有易复制、易修改等特点&#xff0c; 因而数据产品在使用、流通过程中面临被非法复制、非法传播、非法篡改和知识产权窃取等安全风险。在存证数 据上链过程中&a…

PDF转化为机器可读格式的工具

MinerU PDF转化为机器可读格式的工具 项目简介 MinerU是一款将PDF转化为机器可读格式的工具&#xff08;如markdown、json&#xff09;&#xff0c;可以很方便地抽取为任意格式。 项目地址&#xff1a; https://github.com/opendatalab/MinerU/tree/master主要功能 删除页…

微信开发者工具 自定义字体大小

常用编程软件自定义字体大全首页 文章目录 前言具体操作1. 打开文件设置对话框2. 在Font Family里面输入字体 前言 微信开发者工具 自定义字体大小&#xff0c;统一设置为 Cascadia Code SemiBold &#xff0c;大小为 14 具体操作 【文件】>【首选项】>【设置】>【文…

登录校验组件 Spring Security OAuth2 详解

什么是OAuth? OAuth&#xff08;全称Open Authorization&#xff0c;开放授权&#xff09;是一种基于令牌的身份验证和授权协议&#xff0c;它允许用户授权第三方应用访问其在服务提供者&#xff08;如社交媒体、邮箱服务等&#xff09;上存储的特定信息&#xff0c;而无需直…

安防监控/软硬一体/视频汇聚网关EasyCVR硬件启动崩溃是什么原因?

安防视频监控EasyCVR安防监控视频系统采用先进的网络传输技术&#xff0c;支持高清视频的接入和传输&#xff0c;能够满足大规模、高并发的远程监控需求。EasyCVR平台支持多种视频流的外部分发&#xff0c;如RTMP、RTSP、HTTP-FLV、WebSocket-FLV、HLS、WebRTC、WS-FMP4、HTTP-…

PyTorch深度学习网络(二:CNN)

卷积神经网络&#xff08;CNN&#xff09;是一种专门用于处理具有类似网格结构数据的深度学习模型&#xff0c;例如图像&#xff08;2D网格的像素&#xff09;和时间序列数据&#xff08;1D网格的信号强度&#xff09;。CNN在图像识别、图像分类、物体检测、语音识别等领域有着…

API网关之Kong

Kong 是一个高性能的开源 API 网关和微服务管理平台&#xff0c;用于管理、保护和扩展 API 和微服务。它最初由 Mashape 公司开发&#xff0c;并于 2015 年作为开源项目发布。Kong 能够处理 API 的路由、认证、负载均衡、缓存、监控、限流等多种功能&#xff0c;是微服务架构中…

Mysql中count(*) over 用法讲解

Mysql中count&#xff08;*&#xff09; over &#xff08;&#xff09;用法讲解 一、原理1、原理介绍 二、下面是一个使用COUNT(*) OVER()的代码示例&#xff1a;1、代码示例2、结果详解3、COUNT(*) OVER() 分区用法 三 、总结 一、原理 1、原理介绍 在MySQL中&#xff0c;C…

MySQL集群的基础部署及主从复制详解

一、Msql在服务器中的部署方法 官网&#xff1a;http://www.mysql.com 在企业中90%的服务器操作系统均为Linux 在企业中对于Mysql的安装通常用源码编译的方式来进行 1.1 在Linux下部署MySQL 1.1.1 部署环境 主机IP角色MySQL-node1172.25.254.13masterMySQL-node2172.25.…

【C语言】深入理解指针(四)qsort函数的实现

指针4 1.回调函数是什么2.qsort使用举例3.qsort函数的模拟实现 1.回调函数是什么 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#xff0c;被调⽤的…