Java 设计模式实战系列—工厂模式

news2024/12/23 20:19:02

在 Java 开发中,对象的创建是一个常见的场景,如果对象的创建和使用都写在一起,代码的耦合度高,也不利于后期的维护。我们可以使用工厂模式来解决这个问题,工厂模式是一个创建型模式,将对象的创建和使用分离开来,降低代码的耦合度,提高程序的可维护性和扩展性。

工厂模式应用场景

  • 调用方无需关注对象的创建过程,只需要直接调用即可。
  • 具体子类的数目不确定,后续可能会新增或者减少子类的数量。对子类的使用不确定
  • 调用方根据参数来调用对应的对象。

从多种支付种类说起

电商平台下单之后,支付需要可以选择不同的支付的方式,比如拼多多下单后,就会有以下的支付方式:

工厂模式定义:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

创建支付接口以及实现类

首先定义一个支付接口,以及几个实现类,比如微信支付,支付宝支付:

// 支付接口
public interface Pay {
    void pay();
}

// 支付宝支付
public class AliPay implements Pay{
    @Override
    public void pay() {
        System.out.println("支付宝支付 .....");
    }
}

// 微信支付
public class WechatPay implements Pay{

    @Override
    public void pay() {
        System.out.println("微信支付 .....");
    }
}

没使用工厂模式之前,一个下单方法里面包含创建订单、支付、更新订单方法,所以代码都冗余到了一起:

public void order(int payType) {
    // 创建订单
    // 省略代码......
    // 根据type 调用不同的支付
    Pay pay;
    if (payType == 1) {
        pay = new AliPay();
    } else {
        pay = new WechatPay();
    }
    // 调用支付
    pay.pay();
    // 更新状态 代码省略.....
}

以上代码耦合度很高,有以下几个缺点:

  • 违反单一职责原则,对象的创建散落在多个地方,没有一个统一的地方处理对象创建,代码耦合度高。
  • 代码可读性差,后续阅读代码难度增加。
  • 难以扩展和修改,后续添加新的支付方法,或者更修支付方式,需要在多个地方修改代码,增加代码的维护成本。

引入工厂类

将 order 方法的支付代码抽取到工厂类中:

// 支付工厂类
public class PayFactory {

  public static Pay getPay(int payType) {
      Pay pay;
      if (payType == 1) {
          pay = new AliPay();
      } else {
          pay = new WechatPay();
      }
      return pay;
  }

}

经过重构之后的 order 方法,支付直接调用 PayFactory 工厂类,代码逻辑更加清晰,可读性也更强了:

public void order2(int payType) {
    // 创建订单
    // 省略代码......
    // 根据type 调用不同的支付
    Pay pay  = PayFactory.getPay(payType);
    // 调用支付
    pay.pay();
    // 更新状态 代码省略.....

}

  • 引入工厂模式之后,代码有如下的优点:

    • 实现对象的创建和使用解耦,调用方无需关注对象的创建,直接调用即可。
    • 增加的代码的可扩展性和灵活性,添加或者修改对象,只需要在工厂类修改即可,降低代码的维护成本。
    • 代码可读性大大增加。

需要注意的是,上面示例类只有一个方法,仅仅是因为方便,还可以写其他方法,因为工厂模式重点是对象的创建,所以可以包含多个方法

工厂模式在 JDK 中的应用

工厂模式作为场景的一种设计模式,在 JDK 使用也比较广泛,这里就介绍几种使用示例。

Calendar.getInstance

Calendar 类提供了大量跟日期相关的功能代码,Calendar 是一个抽象类,通过调用 Calendar.getInstance() 来获取对象,最终会调用 createCalendar方法,来看一下源码:

从代码可以看出 getInstance 根据 TimeZone 和 Locale 的不同的,返回不同的 Calendar 子类对象,比如 BuddhistCalendar、JapaneseImperialCalendar。将对象的创建封装成一个工厂方法,调用只需要传递当时时区和地址,就能获取到对应的对象了,无需关心对象是如何创建的。

总结

  • 在 Java 开发中如果将对象的创建和使用耦合在一起,不利于后期的维护,这就需要引入工厂模式。
  • 工厂模式将对象的创建和使用分离,降低代码的耦合度。
  • 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
  • 引入工厂模式之后,调用方无需关注对象的创建过程,根据传参调用对应的实例对象,后续新增或更新对象只需要修改工厂方法即可,降低代码的维护成本。

参考

  • 菜鸟教程-工厂模式

  • 极客时间-工厂模式(上)

  • 开源实战一(上):通过剖析Java JDK源码学习灵活应用设计模式

感觉不错的话,点点关注!!!

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

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

相关文章

树莓派使用Nginx 搭建轻量级网站远程访问

文章目录 1. Nginx安装2. 安装cpolar3.配置域名访问Nginx4. 固定域名访问5. 配置静态站点 转载自cpolar极点云文章:树莓派使用Nginx 搭建轻量级网站远程访问 安装 Nginx(发音为“engine-x”)可以将您的树莓派变成一个强大的 Web 服务器&#…

AMEYA360报道:瑞萨电子坐上MCU头把交椅背

综合IC Insights和拓墣产业研究院多方数据来看,2020年之后全球MCU市场增长动力强劲,尤其是汽车MCU市场,有着爆发的态势。具体来看,2022年全球MCU市场规模达到215亿美元,2021年-2026年期间市场的年复合增长率预计将达到…

Java性能权威指南-总结21

Java性能权威指南-总结21 Java EE性能调优对象序列化transient字段覆盖默认的序列化压缩序列化数据 Java EE性能调优 对象序列化 不同系统间的数据交换可以使用XML、JSON和其他基于文本的格式。Java进程间交换数据,通常就是发送序列化后的对象状态。尽管序列化在J…

记一次 .NET 使用 csreids 连接 Redis 超时问题

背景: 使用windows server 2016 , IIS 部署的程序运行一段时间后出现异常, Redis 部署在内网其他服务器; 通过windows 事件查看器发现一些错误日志 , CSRedis.Internal.IO.RedisSocketException: Connect to server timeout 大概意思为连接redis服务 超时; 错误 2023/6/29 11…

通过 Python 控制 AWG70001 发送任意波

0. 实验准备 泰克 AWG70001 一台电脑 一根网线 使用网线连接 AWG70001 和电脑,并且配置 IP 在同一网段下 1. 环境要求 vxi11 numpy struct matplotlib 没有的库可以使用下面的命令安装 pip install vxi11 pip install numpy pip install struct pip install matp…

苹果iphone如何备份整个手机 苹果怎么查备份的照片

手机上的数据变得越来越重要,大家也越来越注重数据安全。如果手机设备丢失的话,不仅是设备的丢失,还是数据的丢失。因此,备份数据就显得很重要。那么,iphone如何备份整个手机,苹果怎么查备份的照片&#xf…

C++day4

2、 #include <iostream>using namespace std;class Person { private:int age;int *p; public://无参构造Person():p(new int(89)){age 18;}//有参构造Person (int age,int num){this->age age;this-> p new int(num);}//拷贝构造函数(深度拷贝)Person(Person …

NTP时钟服务器推荐-国内时间服务器顶尖设备

电子钟时间服务器在物联网应用中起到了关键的作用&#xff0c;它能够为各种智能设备提供准确的时间参考&#xff0c;确保设备之间的协同工作和数据的准确传输。无论是智能家居、智能工厂还是智慧城市&#xff0c;电子钟时间服务器都是不可或缺的一部分。 一、产品卖点 时间服…

启动spring boot项目时加载配置文件报错的问题

最近把电脑重置了一下&#xff0c;然后重新安装各种软件&#xff0c;从gitee拉去项目到本地运行时居然启动报错了 Failed to load property source from file:/D:/program/IdeaProjects/layui/target/classes/application.yml 这是加载配置文件的时候失败了&#xff0c;提示一堆…

Multiple HTTP implementations were found on the classpath错误的解决方法

当我们的项目中集成了多个AWS相关Jar包时,有可能就会遇到这个错误: 错误信息: There is an issue with the connector Code: InvalidInput.InvalidConnectorConfiguration Message: The connector configuration is invalid. Message: Multiple HTTP implementations were f…

自定义MVC架构【上】

目录 一、前言 1.什么是MVC架构 2.使用MVC架构的好处 3.MVC架构与三层架构的区别 4.MVC架构的思路 二、自定义MVC 1.最初版本 2.进阶版 3.反射优化版 4.反射增强版 一、前言 1.什么是MVC架构 MVC架构&#xff08;Model-View-Controller&#xff09;&#xff0c;即模…

【MSP432电机驱动设计—下篇】霍尔编码器测车轮运行距离与M/T综合公式法测速概念

开发板型号为MSP432P401r 今日得以继续我的MSP432电赛速通之路&#xff0c;本篇使用MSP432编程学习霍尔编码器M/T公式法测速概念&#xff0c;最终实现用外部中断方式测得小车行走路程&#xff0c;文章学习讲解原理、附上实例实践、附上关键代码、附上…

微信月活破10亿,安全性靠谁来支撑?

&#x1f449;腾小云导读 微信作为月活过10亿的国民级应用&#xff0c;其安全能力备受关注。值得注意的是&#xff0c;没有足够的特征数据&#xff0c;安全策略将是"无根之木&#xff0c;无源之水"。微信安全数据仓库作为安全业务的特征数据存储中心&#xff0c;每天…

【C/C++】解析 类成员属性

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

JVM类加载双亲委派-JVM(二)

上篇文章说了java类的加载&#xff0c;验证、准备、解析、初始化。类的初始化必须是类加载完才执行&#xff0c;所以类的构造方法初始化是在静态方法之后执行。 JVM类加载机制-JVM&#xff08;一&#xff09; 一、类加载和双亲委派机制 前面类加载主要通过类加载器实现&…

JavaWeb小记——登录、注册

目录 登录项目 步骤 1.首先写一个前台页面&#xff0c;一个form表单——login.jsp 2.后台获取前台输入的参数&#xff0c;并作校验 3.写一个JDBC工具类&#xff0c;用来连接数据库&#xff0c;本案例使用Druid连接池 4.写一个登录工具类&#xff0c;在数据库中查询数据&…

【云原生】k8s的pod基础(上)

1.pod的相关知识 1.1 pod的基础概念 pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是用绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管…

C++面试需求

一.auto 1.介绍&#xff1a; auto 是一个用于类型推导的关键字。它允许变量的类型在编译时根据其初始化值自动推断 例子&#xff1a; &#xff08;1&#xff09;自动类型推导变量 // C program to demonstrate working of auto // and type inference#include <bits/std…

shell正则入门

1.系统通配符 * #所有 . #当前目录 .. #当前目录的上一级目录 - #当前目录的上一次所在的目录 ~ #家目录 # #注释&#xff0c;超级管理员的命令行提示符 $ #引用变量&#xff0c;普通用户的命令行提示符 ? #匹配任意…

Spring Cloud Alibaba体系使用Nacos作为服务注册发现与配置中心

文章目录 Nacos介绍服务注册发现Nacos Discovery引入Nacos DiscoveryProvider和Consumer示例ProviderConsumer Nacos Discovery Starter其他配置选项 服务注册发现Nacos Config引入Nacos Config快速接入配置自动刷新profile粒度控制自定义namespace配置支持自定义Group支持自定…