• 临近秋招,备战暑期实习,祝大家每天进步亿点点!Day17
  • 本篇总结的是 工厂设计模式,后续会每日更新~


1、工厂模式简介

  • ⼯⼚模式介绍:它提供了⼀种创建对象的最佳⽅式,在创建对象时 不会对客户端暴露创建逻辑,并且是通过使⽤⼀个共同的接⼝来指向新创建的对象
  • 例⼦:
    • ⼯⼚⽣产电脑,除了 A 品牌、还可以⽣产B、C、D品牌电脑;
    • 业务开发中,⽀付很常⻅,⾥⾯有统⼀下单和⽀付接 ⼝,具体的⽀付实现可以微信、⽀付宝、银⾏卡等;
  • ⼯⼚模式有 3 种不同的实现⽅式:
    • ① 简单⼯⼚模式(静态工厂):通过传⼊相关的类型来返回相应的类,这 种⽅式⽐较单 ⼀,可扩展性相对较差。
    • ② ⼯⼚⽅法模式:通过实现类实现相应的⽅法来决定相应的返回结果,这种⽅式的可扩展性⽐较强。
    • ③ 抽象⼯⼚模式:基于上述两种模式的拓展,且⽀持细化产品。
  • 应⽤场景:
    • 解耦:分离职责,把复杂对象的创建和使⽤的过程分开。
    • 复⽤代码 降低维护成本:如果对象创建复杂且多处需⽤到,如果每处都进⾏编写,则很多重复代码,如果业务逻辑发⽣了改 变,需⽤四处修改;使⽤⼯⼚模式统⼀创建,则只要修改⼯⼚类即可, 降低成本。

2、工厂模式——简单工厂模式

  • ⼜称静态⼯⼚⽅法,可以根据参数的不同返回不同类的实例,专⻔定义⼀个类来负责创建其他类的实例,被创建的实例通常都具有共同的⽗类。由于⼯⼚⽅法是静态⽅法,可通过类名直接调⽤,⽽且只需要传⼊简单的参数即可。

  • 核⼼组成:

    • Factory:⼯⼚类,简单⼯⼚模式的核⼼,它负责实现 创建所有实例的内部逻辑。
    • IProduct:抽象产品类,简单⼯⼚模式所创建的所有对象的⽗类,描述所有实例所共有的公共接⼝。
    • Product:具体产品类,是简单⼯⼚模式的创建⽬标。
  • 实现步骤:

    • 创建抽象产品类,⾥⾯有产品的抽象⽅法,由具体的产 品类去实现。
    • 创建具体产品类,继承了他们的⽗类,并实现具体⽅法。
    • 创建⼯⼚类,提供了⼀个静态⽅法createXXX()⽤来⽣产产品,只需要传⼊你想产品名称。
  • 优点:将对象的创建和对象本身业务处理分离可以降低系统的 耦合度,使得两者修改起来都相对容易。

  • 缺点:

    • ⼚类的职责相对过重,增加新的产品需要修改⼯⼚类的判断逻辑,这⼀点与开闭原则是相违背。
    • 即开闭原则(Open Close Principle)对扩展开放,对修改关闭,程序需要进⾏拓展的时候,不能去修改原有的代码,实现⼀个热插拔的效果。
    • 将会增加系统中类的个数,在⼀定程度上增加了系统的复杂度和理解难度,不利于系统的扩展和维护,创建简单对象就不⽤模式。

下面我们来简单使用一下简单(静态)工厂设计模式:

我们简单使用伪代码模拟一下支付流程:

创建 IProduct 抽象产品接口——IPay

/*** @Auther: csp1999* @Date: 2020/11/07/11:00* @Description: IPay 抽象统一支付下单接口*/
public interface IPay {/*** 统一下单*/void unifiedOrder();
}

创建 Product 具体产品类——AliPay/WeChatPay

AliPay.java

/*** @Auther: csp1999* @Date: 2020/11/07/11:29* @Description: 支付宝支付具体实现类*/
public class AliPay implements IPay{@Overridepublic void unifiedOrder() {System.out.println("支付宝支付统一下单...");}
}

WeChatPay.java

/*** @Auther: csp1999* @Date: 2020/11/07/11:30* @Description: 微信支付具体实现类*/
public class WeChatPay implements IPay{@Overridepublic void unifiedOrder() {System.out.println("微信支付统一下单...");}
}

创建Factory工厂类——SimplePayFactory

/*** @Auther: csp1999* @Date: 2020/11/07/11:31* @Description: 简单支付工厂类(静态工厂类)*/
public class SimplePayFactory {/*** 工厂创建方法:* 根据参数返回对应的支付对象** @param payType* @return*/public static IPay createPay(String payType) {if (payType == null) {return null;} else if (payType.equalsIgnoreCase("WECHAT_PAY")) {return new WeChatPay();} else if (payType.equalsIgnoreCase("ALI_PAY")) {return new AliPay();}// 如果需要扩展,可以编写更剁return null;}
}

测试使用简单支付工厂:

@Test
public void testSimplePayFactory(){IPay wechat_pay = SimplePayFactory.createPay("WECHAT_PAY");IPay ali_pay = SimplePayFactory.createPay("ALI_PAY");wechat_pay.unifiedOrder();ali_pay.unifiedOrder();
}// 输出结果:
// 微信支付统一下单...
// 支付宝支付统一下单...

上述就是工厂设计模式——简单工程(静态工厂的一个简单使用例子),那么我们来分析下其缺点与不足之处:

需求

  • 如果我需要额外再添加一个 A 银行的银行卡支付,那么就需要在SimplePayFactory 类中添加响应的判断逻辑,比如再加一个if判断,添加一个 A 银行支付的逻辑。
  • 而如果再需要一个 B 银行的银行卡支付,那么还需要再添加一个if判断 添加一个 B 银行支付的逻辑,依次加下去…
  • 那么这就违背了⼯⼚类要遵循的开闭原则(Open Close Principle)(对扩展开放,对修改关闭,程序需要进⾏拓展的时候,不能去修改原有的代码,实现⼀个热插拔的效果),这样就导致,每次扩展功能的时候都需要添加新的逻辑,并且需要对工厂类进行修改,如果是真实复杂的业务,这就增加了成本。

下面我们来看一下工厂方法模式是如何解决简单工厂模式的这一缺点:


3、工厂模式——工厂方法模式

  • ⼜称⼯⼚模式,是对简单⼯⼚模式的进⼀步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满⾜开闭原则
  • 通过⼯⼚⽗类定义负责创建产品的公共接⼝,通过⼦类来确定所需要创建的类型。
  • 相⽐简单⼯⼚⽽⾔,此种⽅法具有更多的可扩展性复⽤性,同时也增强了代码的可读性
  • 将类的实例化(具体产品的创建)延迟到⼯⼚类的⼦类 (具体⼯⼚)中完成,即由⼦类来决定应该实例化哪⼀ 个类。
  • 核⼼组成:
    • IProduct:抽象产品接口,描述所有实例所共有的公共接⼝。
    • Product:具体产品类,实现抽象产品类的接⼝,⼯⼚ 类创建对象,如果有多个需要定义多个。
    • IFactory:抽象⼯⼚接口,描述具体⼯⼚的公共接⼝。
    • Factory:具体⼯⼚类,实现创建产品类对象,实现抽 象⼯⼚类的接⼝,如果有多个需要定义多个。

要实现工厂方法模式,只需要在原来的简单工厂模式基础上,做出改进,而之前我们创建的IPay抽象产品接口和AliPayWeChatPay 两个具体产品类不需要改动。

首先创建IPayFactory抽象⼯⼚接口:

/*** @Auther: csp1999* @Date: 2020/11/07/15:08* @Description: 抽象⼯⼚接口*/
public interface IPayFactory {IPay getPay();
}

然后创建AliPayFactoryWeChatFactory 两个具体⼯⼚类:

/*** @Auther: csp1999* @Date: 2020/11/07/15:09* @Description: 具体工厂类 AliPayFactory*/
public class AliPayFactory implements IPayFactory{@Overridepublic IPay getPay() {return new AliPay();}
}
/*** @Auther: csp1999* @Date: 2020/11/07/15:16* @Description: 具体工厂类 WeChatFactory*/
public class WeChatFactory implements IPayFactory{@Overridepublic IPay getPay() {return new WeChatPay();}
}

进行测试:

@Test
public void testMethodPayFactory(){AliPayFactory aliPayFactory = new AliPayFactory();IPay ali_pay = aliPayFactory.getPay();ali_pay.unifiedOrder();// 输出:支付宝支付统一下单...WeChatFactory weChatFactory = new WeChatFactory();IPay wechat_pay = weChatFactory.getPay();wechat_pay.unifiedOrder();// 输出:微信支付统一下单...
}

工厂方法模式思路如下图:

工厂方法模式优点

  • 符合开闭原则,增加⼀个产品类,只需要实现其他具体的产品类和具体的⼯⼚类;
  • 符合单⼀职责原则,每个⼯⼚只负责⽣产对应的产品;

工厂方法模式缺点

  • 增加⼀个产品,需要实现对应的具体⼯⼚类和具体产品类;
  • 每个产品需要有对应的具体⼯⼚和具体产品类;

4、工厂模式——抽象工厂方法模式

抽象⼯⼚⽅法模式是简单工厂模式 和工厂方法模式的整合升级版。象⼯⼚模式在 Spring 中应⽤得最为⼴泛的⼀种设计模式。

背景:

  • ⼯⼚⽅法模式引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责过重的问题。
  • 但⼯⼚⽅法模式中每个⼯⼚只创建⼀类具体类的对象, 后续发展可能会导致⼯⼚类过多,因此将⼀些相关的具体类组成⼀个“具体类族”,由同⼀个⼯⼚来统⼀⽣产, 强调的是⼀系列相关的产品对象!!!

实现步骤:

  • 1、定义两个接⼝ IPay(支付)、IRefund(退款)。
  • 2、创建具体的 Pay产品、创建具体的 Refund 产品。
  • 3、创建抽象⼯⼚ IOrderFactory 接⼝ ⾥⾯两个⽅法 createPay/createRefund。
  • 4、创建⽀付宝产品族 AliOderFactory,实现 OrderFactory 抽象⼯⼚。
  • 5、创建微信⽀付产品族 WechatOderFactory,实现 OrderFactory 抽象⼯⼚。
  • 6、定义⼀个超级⼯⼚创造器 FactoryProducer,通过传递参数获取对应的⼯⼚。

接下来我们就按照步骤使用一下抽象工厂方法模式:

1、定义两个接⼝ IPay(支付)、IRefund(退款):

/*** @Auther: csp1999* @Date: 2020/11/07/16:06* @Description: 支付抽象接口*/
public interface IPay {/*** 统一下单*/void unifiedOrder();
}
/*** @Auther: csp1999* @Date: 2020/11/07/16:07* @Description: 退款抽象接口*/
public interface IReFund {/*** 退款*/void refund();
}

2、创建具体的 Pay 产品、创建具体的 Refund 产品:

AliPay/WeChatPay:支付宝支付和微信支付

/*** @Auther: csp1999* @Date: 2020/11/07/11:29* @Description: 支付宝支付具体实现类*/
public class AliPay implements IPay {@Overridepublic void unifiedOrder() {System.out.println("支付宝支付 统一下单接口...");}
}
/*** @Auther: csp1999* @Date: 2020/11/07/11:30* @Description: 微信支付具体实现类*/
public class WeChatPay implements IPay {@Overridepublic void unifiedOrder() {System.out.println("微信支付统一下单...");}
}

AliRefund/WeChatFund:支付宝退款和微信退款

/*** @Auther: csp1999* @Date: 2020/11/07/16:35* @Description:*/
public class AliRefund implements IReFund {@Overridepublic void refund() {System.out.println("支付宝退款...");}
}
/*** @Auther: csp1999* @Date: 2020/11/07/16:40* @Description:*/
public class WeChatRefund implements IReFund {@Overridepublic void refund() {System.out.println("微信支付退款...");}
}

3、创建抽象⼯⼚ IOrderFactory 接⼝ ⾥⾯两个⽅法 createPay/createRefund:

/*** @Auther: csp1999* @Date: 2020/11/07/16:04* @Description: 订单抽象工厂,一个超级工厂可以创建其他工厂(又被称为其他工厂的工厂)*/
public interface IOrderFactory {IPay createPay();IReFund createRefund();
}

4、创建⽀付宝产品族AliOderFactory,实现OrderFactory 抽象⼯⼚:

/*** @Auther: csp1999* @Date: 2020/11/07/16:18* @Description:*/
public class AliOrderFactory implements IOrderFactory {@Overridepublic IPay createPay() {return new AliPay();}@Overridepublic IReFund createRefund() {return new AliRefund();}
}

5、创建微信⽀付产品族WechatOderFactory,实现 OrderFactory抽象⼯⼚

/*** @Auther: csp1999* @Date: 2020/11/07/16:39* @Description:*/
public class WeChatOrderFactory implements IOrderFactory {@Overridepublic IPay createPay() {return new WeChatPay();}@Overridepublic IReFund createRefund() {return new WeChatRefund();}
}

6、定义⼀个超级⼯⼚创造器FactoryProducer,通过传递参数获取对应的⼯⼚

/*** @Auther: csp1999* @Date: 2020/11/07/16:46* @Description: 工厂创造器*/
public class FactoryProducer {public static IOrderFactory getFactory(String type){if (type.equalsIgnoreCase("WECHAT")){return new WeChatOrderFactory();}else if (type.equalsIgnoreCase("ALI")){return new AliOrderFactory();}return null;}
}

最后我们来进行测试:

@Test
public void testAbstractMethodPayFactory(){IOrderFactory wechatPayFactory = FactoryProducer.getFactory("WECHAT");wechatPayFactory.createPay().unifiedOrder();wechatPayFactory.createRefund().refund();IOrderFactory aliPayFactory = FactoryProducer.getFactory("ALI");aliPayFactory.createPay().unifiedOrder();aliPayFactory.createRefund().refund();
}

结果如下:

微信支付统一下单...
微信支付退款...
支付宝支付 统一下单接口...
支付宝退款...

⼯⼚⽅法模式和抽象⼯⼚⽅法模式

  • 从上面案例可以看出,抽象工厂模式是工厂方法模式和静态工厂模式的合并,即超级工厂使用的是简单工厂模式,受超级工厂管辖的工厂使用的是工厂方法模式。
  • 如图:


总结的面试题也挺费时间的,文章会不定时更新,有时候一天多更新几篇,如果帮助您复习巩固了知识点,还请三连支持一下,后续会亿点点的更新!


为了帮助更多小白从零进阶 Java 工程师,从CSDN官方那边搞来了一套 《Java 工程师学习成长知识图谱》,尺寸 870mm x 560mm,展开后有一张办公桌大小,也可以折叠成一本书的尺寸,有兴趣的小伙伴可以了解一下,当然,不管怎样博主的文章一直都是免费的~

【Java萌新】面试常问设计模式——工厂模式相关推荐

  1. Java程序员面试常问的问题,原来SqlSession只是个甩手掌柜

    PS:doFlushStatements方法在BaseExecutor中的commit(),rollback(),close()方法中会被调用(即:事务提交,事务回滚,事务关闭三个方法). Batch ...

  2. java中高级面试_中高级面试常问:Java面向对象设计的六大原则

    这篇文章主要讲的是面向对象设计中,我们应该遵循的六大原则.只有掌握了这些原则,我们才能更好的理解设计模式.我们接下来要介绍以下6个内容.单一职责原则--SRP 开闭原则--OCP 里式替换原则--LS ...

  3. Java基础(以及面试常问问题)

    1.Vector,ArrayList, LinkedList的区别(面试常问到的) 三者都是实现集合框架中的List,也就是所谓有序集合,因此具体功能比较近似,比如都提供按照位置进行定位.添加或删除的 ...

  4. Java面试常问计算机网络问题

    转载自   Java面试常问计算机网络问题 一.GET 和 POST 的区别 GET请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:/test/demo_form.asp?na ...

  5. 指南Java面试常问问题及答案

    Java 面试常问问题及答案(非常详细) 一:java 基础 1.简述 string 对象,StringBuffer.StringBuilder 区分 string 是 final 的,内部用一个 f ...

  6. servlet面试常问问题_50个Servlet面试问答

    servlet面试常问问题 Servlet是Java EE的一个非常重要的主题,所有Web应用程序框架(例如Spring和Struts)都建立在它之上. 这使servlet成为Java访谈中的热门话题 ...

  7. 冒泡排序java代码_面试官问我插入排序和冒泡排序哪个更牛逼?

    (给算法爱好者加星标,修炼编程内功) 来源:小鹿动画学编程,作者:小鹿同学 写在前边 排序对于每个开发者来讲,都多多少少知道几个经典的排序算法,比如我们之前以动画形式分享的冒泡排序,也包括今天要分享的 ...

  8. 变态级JAVA程序员面试32问(附答案)(转载)

    flyjimi的专栏 君士坦丁堡的血泪 CSDNBlog  |  我的首页  |  联系作者  |  聚合   |  登录      66篇文章 :: 0篇收藏:: 9篇评论:: 0个Trackbac ...

  9. 面向对象程序设计(c++)面试常问——for考研复试面试

    关于c++的一些面试常问问题(考研面试编程语言) 前言: 本人22考研党,已上岸,发一些复试准备整理的资料作为对考研准备的一个收尾.由于近几年基本都是线上复试,线上的话会更加注重概念的考察,本人在复试 ...

最新文章

  1. JTable调整列宽
  2. 关于容量设计、规划、治理 你知多少?
  3. 面试题 04.08. 首个共同祖先
  4. OV摄像头SCCB通信协议
  5. java模拟网银登录_Java模拟网上银行业务
  6. 技术文化和惨淡命运 —— 怀念中国雅虎----转载
  7. Java 添加Word文本框
  8. 【毕设记录日记】深度学习|铝型材表面缺陷视觉检测算法:YOLOv5环境搭建、基础知识、问题解决、优化方法
  9. 对射式光电传感器测速使用CD10406消抖动解决办法
  10. linux 图片压缩命令,Linux:优化和压缩JPEG和PNG图片的命令行工具
  11. 谈互联网产品运营(转载)
  12. 高通FastCV简介
  13. SpringBoot 导出Word文档(doc\docx) Office无法打开,WPS正常等坑
  14. html+js+css 调用jquery 工人信息管理功能(增删改查)前端实现,以及调用实现鼠标拖尾粒子效果的js库
  15. tomcat上面出现红色的×
  16. 吃鸡哪个服务器网络稳定,中国地区吃鸡哪个服务器不卡 | 手游网游页游攻略大全...
  17. plc 梯形图 转c语言,电路与PLC之间的梯形图转化,电气人必备技能!
  18. uni-app 轮播图视频+图片 视频图片全屏预览 两种方法
  19. 蓄电池内阻、电压及温度在线监测系统应用方案
  20. 用什么软件测试家里网络,几个简单小技巧,告诉大家如何知道家里的网速是多少!...

热门文章

  1. 【day004】MyEclipse新建文件操作和Java注释快捷键
  2. 职场牛人的基本功 - 拆解分析能力
  3. 电脑企业微信怎么发送本地文件给微信好友?
  4. Python开发万能钥匙小程序,成功获取邻居家Wifi密码(附源码)!
  5. 奇思乐高机器人怎么样_奇思机器人:如果孩子和优质的教育只有一步之遥,那就是乐高的差距...
  6. 【JAVA】贪吃蛇的初步实现(二)
  7. 中国程序员都不生产代码,只是代码的搬运工?
  8. java jca jce_加解密---Java安全
  9. html tabl自动生成序列号,jQuery实现table中的tr上下移动并保持序号不变的实例代码...
  10. java 转换xml格式的doc或docx文档为docx以及docx转PDF