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

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

工厂模式应用场景

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

从多种支付种类说起

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

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

创建支付接口以及实现类

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

// 支付接口
public interface Pay {void pay();
}// 支付宝支付
public class AliPay implements Pay{@Overridepublic void pay() {System.out.println("支付宝支付 .....");}
}// 微信支付
public class WechatPay implements Pay{@Overridepublic 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.hqwc.cn/news/1475.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Visual Studio】使用 C++ 语言,配合 Qt,开发了一个串口通信界面

知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 文章目录 1. 获取串口名字1.1 文件 GUI.ui1.2 文件 GUI.h1.3 文件 GUI.cpp潜在 Bug:LN2019 2. 配置串口连接2.1 文件 GUI.ui2.2 文件 GUI.h2.3 文…

【C#】简单聊下Framework框架下的事务

框架用的多了,之前版本的事务都忘记了。本次简单聊下.net framework 4.8框架下本身的事务 目录 1、SqlClient2、TransactionScope3、引用 1、SqlClient 在 C# 中,使用 using 块可以方便地实现对资源的自动释放,但它不适用于实现事务处理。为…

一种基于linux内核双向链表的移植

1.简介 双向链表(Doubly Linked List)是一种常见的数据结构,由一系列的节点组成,每个节点都包含两个指针,分别指向前一个节点和后一个节点。与单向链表不同,双向链表可以在 O(1) 的时间复杂度内向前或向后遍…

虚拟机VMware+Ubuntu配置DPDK环境并运行Helloworld

虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld 文章目录 虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld安装虚拟机虚拟机中安装DPDK运行Helloworld 首先需要强调的是,版本的影响很大,有可能会因为版本不匹配而导致无法成功配置DPDK环境。 安装虚拟…

火山引擎 Iceberg 数据湖的应用与实践

在云原生计算时代,云存储使得海量数据能以低成本进行存储,但是这也给如何访问、管理和使用这些云上的数据提出了挑战。而 Iceberg 作为一种云原生的表格式,可以很好地应对这些挑战。本文将介绍火山引擎在云原生计算产品上使用 Iceberg 的实践…

Scrapy框架之认识MongoDB

目录 MongoDB 简介 特点 MongoDB的适用场景 MongoDB的行业具体应用 如何抉择是否使用MongoDB MongoDB 简介 MongoDB 是免费开源的跨平台 NoSQL 数据库,命名源于英文单词 humongous,意思是「巨大无比」,可见开发组对 MongoDB 的定位。…

函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜

函数模板 交换两个整型变量的值的Swap函数: void Swap(int & x,int & y) { int tmp x; x y; y tmp; } 交换两个double型变量的值的Swap函数: void Swap(double & x,double & y) { double tmp x; x y; y tmp; }用函数模板解决: …

计算几何——gitf-wrapping算法

几何中的"gift-wrapping"算法,又称为"Jarvis算法",是一种用于计算凸包(convex hull)的方法。下面我将为你解释一下该算法的步骤: 1. 找到具有最小x坐标的点P,我们将其作为凸包的起点。 2. 将P标记为当前点&a…

Java Spring概述

1、Spring是什么? Spring 是一款主流的 Java EE 轻量级开源框架 ,Spring 由“Spring 之父”Rod Johnson 提出并创立,其目的是用于简化 Java 企业级应用的开发难度和开发周期。Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦…

MySQL 备份与恢复

MySQL 备份与恢复 一、数据库备份的分类1.1 数据备份的重要性1.2 数据库备份的分类1.2.1 从物理与逻辑的角度,分为物理备份和逻辑备份1.2.2 从数据库的备份策略角度,分为完全备份,差异备份和增量备份1.2.3 常见的备份方法 二、MySQL完全备份与…

GreenPlum版本升级

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

10个图像处理的Python库

在这篇文章中,我们将整理计算机视觉项目中常用的Python库,如果你想进入计算机视觉领域,可以先了解下本文介绍的库,这会对你的工作很有帮助。 1、PIL/Pillow Pillow是一个通用且用户友好的Python库,提供了丰富的函数集…