常用设计模式——深入理解工厂模式

男娘i 2022-03-11 12:38 346阅读 0赞

工厂模式
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式 在设计模式当时它属于创建性模式 而它却又分成了简单工厂模式、工厂方法模式、抽象工厂模式。

场景:
在开发过程中想必大家都对接过支付接口,而在选择支付方式的时候常常有很多种,如银联、支付宝 等,在随着系统逐渐运行,假如我们现在需要添加微信支付,而在这时我们怎么应对系统扩展呢?

一:简单工厂

定义:简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现

上代码:
我们先创建一个支付接口,接着创建支付宝支付,微信支付 代码如下:

支付接口:

  1. package com.designpattern.factory;
  2. /**
  3. * 支付接口
  4. * zhan_lang
  5. */
  6. public interface Pay {
  7. void create();
  8. }

支付宝支付:

  1. package com.designpattern.factory;
  2. /**
  3. * 支付宝支付
  4. * zhan_lang
  5. */
  6. public class AliPay implements Pay {
  7. @Override
  8. public void create() {
  9. System.out.println("支付宝支付");
  10. }
  11. }

微信支付:

  1. package com.designpattern.factory;
  2. /**
  3. * 微信支付
  4. * zhan_lang
  5. */
  6. public class Wechat implements Pay {
  7. @Override
  8. public void create() {
  9. System.out.println("微信支付");
  10. }
  11. }

现在我们支付方式有了 那么我们怎么来获取支付方式呢?在这里简单工厂只需要获取对象实例即可,代码实现如下:

  1. package com.designpattern.factory.simple;
  2. import com.designpattern.factory.AliPay;
  3. import com.designpattern.factory.Pay;
  4. import com.designpattern.factory.Wechat;
  5. import org.springframework.util.StringUtils;
  6. /**
  7. * zhan_lang
  8. * 简单工厂创建类
  9. */
  10. public class PayFactory {
  11. /**
  12. * 简单方式
  13. * @param name
  14. * @return
  15. */
  16. public Pay create(String name){
  17. if ("wechat".equals(name)){
  18. return new Wechat();
  19. }else if ("alipay".equals(name)){
  20. return new AliPay();
  21. }
  22. return null;
  23. }
  24. /**
  25. * className 方式
  26. * @param s
  27. */
  28. public Pay createByClassName(String s) {
  29. try {
  30. if (!StringUtils.isEmpty(s)){
  31. return (Pay) Class.forName(s).newInstance();
  32. }
  33. }catch (Exception e){
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }
  38. /**
  39. * clazz
  40. * @param clazz
  41. */
  42. public Pay createByClazz(Class<?> clazz) {
  43. try {
  44. if (clazz != null){
  45. return (Pay) clazz.newInstance();
  46. }
  47. }catch (Exception e){
  48. e.printStackTrace();
  49. }
  50. return null;
  51. }
  52. }

获取对象实例写好了 我们来调用一波,

  1. package com.designpattern.factory.simple;
  2. import com.designpattern.factory.AliPay;
  3. import com.designpattern.factory.Pay;
  4. import com.designpattern.factory.Wechat;
  5. /**
  6. * 简单工厂
  7. * 优点:只需要传入一个正常的参数则可以获取一个实例 无需关注创建过程
  8. * 缺点:创建过程简单 不易于扩展 如果新增工厂类 需要修改判断 违背了开闭原则
  9. * zhan_lang
  10. */
  11. public class PayTest {
  12. public static void main(String[] args) {
  13. //未用工厂
  14. Pay pay = new Wechat();
  15. pay.create();
  16. //最原始方式(必须传入正常字符串判断)
  17. PayFactory payFactory = new PayFactory();
  18. payFactory.create("alipay").create();
  19. //ClassName 必须传入正常包点类名
  20. PayFactory payFactory1 = new PayFactory();
  21. payFactory1.createByClassName("com.designpattern.factory.AliPay").create();
  22. //calzz 传入已有类
  23. PayFactory payFactory2 = new PayFactory();
  24. payFactory2.createByClazz(AliPay.class).create();
  25. }
  26. }

简单工厂模式就是如此简单 只需要提供创建对象实例的方法就可以了 但是这里请注意 我们在判断获取哪个对象实例的时候 如果还是用if-else-if 来判断是不是有点说不过去了(太low了 有100种实例 你会判断100次吗 反正我不会) 所以我们改用以反射的方式来获取对象实例。
至于简单工厂模式的优缺点 在调用的时候已经写出来 这里就不在啰嗦了。

二:工厂方法模式

定义:工厂方法模式使用的频率非常高,在我们日常开发中总是能看到它的影子,其定义为:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。

上代码:
这里我们还是运用支付方式来跟大家讲解 对象实例还是运用简单工厂模式里面的实例 但是我们这里需要单独创建一个工厂接口 抽象出一个支付接口 然后支付方式去实现工厂接口 这样我们创建类的实例就可以延迟到子类了。代码如下:

工厂接口:

  1. package com.designpattern.factory.factory;
  2. import com.designpattern.factory.Pay;
  3. /**
  4. * 工厂接口
  5. * zhan_lang
  6. */
  7. public interface PayFactory {
  8. //如果工厂类需要自己的业务逻辑处理 则可以将接口改成抽象类来保留
  9. Pay create();
  10. }

创建对象实例:在这里我们就这个类实例化过程交给了子类了

  1. package com.designpattern.factory.factory;
  2. import com.designpattern.factory.AliPay;
  3. import com.designpattern.factory.Pay;
  4. /**
  5. * zhan_lang
  6. */
  7. public class AliPayFactory implements PayFactory {
  8. @Override
  9. public Pay create() {
  10. return new AliPay();
  11. }
  12. }

老规矩调用一波:

  1. package com.designpattern.factory.factory;
  2. import com.designpattern.factory.Pay;
  3. /**
  4. * 工厂方法模式
  5. * 优点:没有违背开闭原则 提高了扩展性 类过多(新增则需要添加工厂类和基类)
  6. * 缺点:增加了系统的抽象性和理解难度
  7. * zhan_lang
  8. */
  9. public class PayTest {
  10. public static void main(String[] args) {
  11. PayFactory payFactory = new AliPayFactory();
  12. Pay pay = payFactory.create();
  13. pay.create();
  14. }
  15. }

这样工厂方法模式就完成了 但是需要注意的是 工厂接口不仅仅只能是接口类型 如果它有自己的业务逻辑 则可以将接口改成抽象类 这里我们就不演示代码了

三:抽象工厂模式

在简单工厂和工厂方法模式当中 支付方式是出来了 在一个传统的支付当中 光有支付怎么行 我们的支付记录呢 那这种情况我们又该怎么办呢?请看抽象工厂模式

定义:抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类
上代码:
这里我们先创建工厂接口 并提供支付和支付记录两个接口

  1. package com.designpattern.factory.abstractfactory;
  2. /**
  3. * 抽象顶层接口
  4. * 在真实的支付场景中 我们是不光只有支付过程的 我们还有支付记录 对于这样一个系列多个产品的场景我们怎么来处理呢?
  5. * zhan_lang
  6. */
  7. public interface PayFactory {
  8. IPay createPay();
  9. IPayRecord createRecord();
  10. }

然后创建支付接口并提供方法

  1. package com.designpattern.factory.abstractfactory;
  2. /**
  3. * 支付
  4. * zhan_lang
  5. */
  6. public interface IPay {
  7. void createPay();
  8. }
  9. package com.designpattern.factory.abstractfactory;
  10. /**
  11. * 创建支付宝支付
  12. * zhan_lang
  13. */
  14. public class AliPay implements IPay {
  15. @Override
  16. public void createPay() {
  17. System.out.println("创建支付宝支付");
  18. }
  19. }

创建支付记录接口并提供方法

  1. package com.designpattern.factory.abstractfactory;
  2. /**
  3. * 支付记录
  4. * zhan_lang
  5. */
  6. public interface IPayRecord {
  7. void createRecord();
  8. }
  9. package com.designpattern.factory.abstractfactory;
  10. /**
  11. * 产生支付记录
  12. * zhan_lang
  13. */
  14. public class AliPayRecord implements IPayRecord {
  15. @Override
  16. public void createRecord() {
  17. System.out.println("产生支付记录");
  18. }
  19. }

创建支付宝工厂类 并提供支付和支付记录方法

  1. package com.designpattern.factory.abstractfactory;
  2. /**
  3. * 支付宝工厂
  4. */
  5. public class AliPayFactory implements PayFactory {
  6. @Override
  7. public IPay createPay() {
  8. return new AliPay();
  9. }
  10. @Override
  11. public IPayRecord createRecord() {
  12. return new AliPayRecord();
  13. }
  14. }

最后调用一波

  1. package com.designpattern.factory.abstractfactory;
  2. /**
  3. * 抽象工厂模式
  4. * 优点:将一个系列的多个产品一起创建
  5. * 缺点:增加了系统的抽象性和理解难度 扩展新的产品比较困难 需要修改抽象工厂接口
  6. * zhan_lang
  7. */
  8. public class AbstractFactoryTest {
  9. public static void main(String[] args) {
  10. PayFactory payFactory = new AliPayFactory();
  11. payFactory.createPay().createPay();
  12. payFactory.createRecord().createRecord();
  13. }
  14. }

完美实现 有没有 ?这里同工厂方法模式一样 如果工厂接口有其他业务逻辑 可以换成抽象类来实现
最后将类图提供给大家 方便大家理解 在idea当中 显示类图快捷键为:ctrl+Shift+Alt+U
在这里插入图片描述

在这里工厂方法模式就介绍完了 你了解了吗?
最后,最后提醒大家 要学以致用 这样才不会忘 才能写出更高逼格的代码 !

发表评论

表情:
评论列表 (有 0 条评论,346人围观)

还没有评论,来说两句吧...

相关阅读

    相关 深入理解工厂模式

    一、工厂模式 1.1定义 (在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。) 1.2工厂模式的分类: (1)