Java 设计模式实战系列—工厂模式
在 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 设计模式实战系列—工厂模式的更多相关文章
- Java 设计模式之抽象工厂模式(三)
原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...
- Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)
Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...
- Java设计模式之二 ----- 工厂模式
在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又 ...
- Java设计模式之二工厂模式
在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法.本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式.工厂方法和抽象工厂模式. 简单工厂模式 简单工厂模式是属于创建型模式,又 ...
- java设计模式---三种工厂模式
工厂模式提供创建对象的接口. 工厂模式分为三类:简单工厂模式(Simple Factory), 工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory).GOF在 ...
- java设计模式2--抽象工厂模式(Abstract Factory)
本文地址:http://www.cnblogs.com/archimedes/p/java-abstract-factory-pattern.html,转载请注明源地址. 抽象工厂模式(别名:配套) ...
- java设计模式之抽象工厂模式
上一篇文章(http://www.cnblogs.com/liaoweipeng/p/5768197.html)讲了简单工厂模式,但是简单工厂模式存在一定的问题,如果想要拓展程序,必须对工厂类进行修改 ...
- Java设计模式学习之工厂模式
在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了.Java 设计模式之工厂模式 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低 ...
- Java设计模式学习三-----工厂模式
工厂模式 工厂模式(Factory Pattern)是Java中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,创建对象时不会对客户端暴露创建逻 ...
- 【java设计模式】-02工厂模式
工厂模式简述 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客 ...
随机推荐
- Python安装-在Linux系统中使用编译进行安装
Python安装-在Linux系统中使用编译进行安装 你可以使用Ubuntu自带的Python3,不过你不能自由的控制版本,还要单独安装pip3,如果你想升级pip3,还会出现一些让人不愉快的使用问题 ...
- OpenTiny 跨端、跨框架组件库升级TypeScript,10万行代码重获新生
摘要:一份精心准备的<JS项目改造TS指南>文档供大家参考,顺便介绍TS 基础知识和 TS 在 Vue 中的实践. 本文分享自华为云社区<历史性的时刻!OpenTiny 跨端.跨框架 ...
- LeeCode 319周赛复盘
T1: 温度转换 思路:模拟 public double[] convertTemperature(double celsius) { return new double[]{celsius + 27 ...
- Git多平台/多账号配置
有时候需要在一台电脑使用多个git平台(Gitee.GitHub.Gitlab...)或者一个平台多个不同账号,比如想同时配置公司git和个人的git,提交代码时提交到对应的平台/账号的代码仓库且互不 ...
- vulnhub靶场之CROSSROADS: 1
准备: 攻击机:虚拟机kali.本机win10. 靶机:Crossroads: 1,下载地址:https://download.vulnhub.com/crossroads/crossroads_vh ...
- 彻底搞懂Redis持久化机制,轻松应对工作面试
1. 为什么要持久化 Redis是基于内存存储的数据库,如果遇到服务重启或者崩溃,内存中的数据将会被清空.所以为了确保数据安全性和可靠性,我们需要将内存中的数据持久化到磁盘上. 持久化不仅可以防止由于 ...
- springboot-poi ---封装注解式导入导出
此demo 是基于poi封装对象式注解导入导出,项目框架为springboot项目! 简单的说明一下此demo涉及到的知识点,希望能给初学者带来方便! poi-excel 基本操作(工具) 自定义注解 ...
- DRF的限流组件(源码分析)
DRF限流组件(源码分析) 限流,限制用户访问频率,例如:用户1分钟最多访问100次 或者 短信验证码一天每天可以发送50次, 防止盗刷. 对于匿名用户,使用用户IP作为唯一标识. 对于登录用户,使用 ...
- 笔记:C++学习之旅---指针
笔记:C++学习之旅---指针 为什么要使用指针 因为在操作大型数据和类时,由于指针可以通过内存地址直接访问数据,从而避免在程序中赋值大量的代码,因此指针的效率最高,一般来说,指针会有三大用途: 1: ...
- Python_17 OSI模型和HTTP协议
一.查缺补漏 1. Wireshark 抓报文 2. 要学习的所有博客: http://testingpai.com/member/haili/articles二.OSI模型 1. 物理层 2. 数据 ...