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

 

此文转载乐字节
本篇总结的是 工厂设计模式,后续会每日更新~


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();
}
1
2
3
4
5
6
7
8
9
10
11
12
创建 Product 具体产品类——AliPay/WeChatPay:

AliPay.java

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/11:29
 * @Description: 支付宝支付具体实现类
 */
public class AliPay implements IPay{
    @Override
    public void unifiedOrder() {
        System.out.println("支付宝支付统一下单...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
WeChatPay.java

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/11:30
 * @Description: 微信支付具体实现类
 */
public class WeChatPay implements IPay{
    @Override
    public void unifiedOrder() {
        System.out.println("微信支付统一下单...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
创建Factory工厂类——SimplePayFactory:

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/11:31
 * @Description: 简单支付工厂类(静态工厂类)

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

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

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

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/15:08
 * @Description: 抽象⼯⼚接口
 */
public interface IPayFactory {
    IPay getPay();
}
1
2
3
4
5
6
7
8
然后创建AliPayFactory和WeChatFactory 两个具体⼯⼚类:

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/15:09
 * @Description: 具体工厂类 AliPayFactory
 */
public class AliPayFactory implements IPayFactory{
    @Override
    public IPay getPay() {
        return new AliPay();
    }
}
1
2
3
4
5
6
7
8
9
10
11
/**
 * @Auther: csp1999
 * @Date: 2020/11/07/15:16
 * @Description: 具体工厂类 WeChatFactory
 */
public class WeChatFactory implements IPayFactory{
    @Override
    public IPay getPay() {
        return new WeChatPay();
    }
}
1
2
3
4
5
6
7
8
9
10
11
进行测试:

@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();// 输出:微信支付统一下单...
}
1
2
3
4
5
6
7
8
9
工厂方法模式思路如下图:

工厂方法模式优点:

符合开闭原则,增加⼀个产品类,只需要实现其他具体的产品类和具体的⼯⼚类;
符合单⼀职责原则,每个⼯⼚只负责⽣产对应的产品;
工厂方法模式缺点:

增加⼀个产品,需要实现对应的具体⼯⼚类和具体产品类;
每个产品需要有对应的具体⼯⼚和具体产品类;
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();
}
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * @Auther: csp1999
 * @Date: 2020/11/07/16:07
 * @Description: 退款抽象接口
 */
public interface IReFund {

    /**
     * 退款
     */
    void refund();
}
1
2
3
4
5
6
7
8
9
10
11
12
2、创建具体的 Pay 产品、创建具体的 Refund 产品:

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

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/11:29
 * @Description: 支付宝支付具体实现类
 */
public class AliPay implements IPay {

    @Override
    public void unifiedOrder() {
        System.out.println("支付宝支付 统一下单接口...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * @Auther: csp1999
 * @Date: 2020/11/07/11:30
 * @Description: 微信支付具体实现类
 */
public class WeChatPay implements IPay {
    @Override
    public void unifiedOrder() {
        System.out.println("微信支付统一下单...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
AliRefund/WeChatFund:支付宝退款和微信退款

/**
 * @Auther: csp1999
 * @Date: 2020/11/07/16:35
 * @Description:
 */
public class AliRefund implements IReFund {
    @Override
    public void refund() {
        System.out.println("支付宝退款...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
/**
 * @Auther: csp1999
 * @Date: 2020/11/07/16:40
 * @Description:
 */
public class WeChatRefund implements IReFund {
    @Override
    public void refund() {
        System.out.println("微信支付退款...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
3、创建抽象⼯⼚ IOrderFactory 接⼝ ⾥⾯两个⽅法 createPay/createRefund:

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

    IPay createPay();

    IReFund createRefund();
}
1
2
3
4
5
6
7
8
9
10
11
4、创建⽀付宝产品族AliOderFactory,实现OrderFactory 抽象⼯⼚:

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

    @Override
    public IReFund createRefund() {
        return new AliRefund();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
5、创建微信⽀付产品族WechatOderFactory,实现 OrderFactory抽象⼯⼚

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

    @Override
    public IReFund createRefund() {
        return new WeChatRefund();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
最后我们来进行测试:

ps需自学视频2021最新springboot+MybatisPlubs+maven商务ERP进销存管理系统实战-关注B站:BV13b4y1d7JW?p=2&spm_id_from=pageDriver

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值