工厂模式(Factory Pattern)(二)

简介: 工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的绝佳方式。

前言
iShot2022-12-05 00.30.04.png
工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的绝佳方式。

工厂方法模式

上篇文章我们学习了简单工厂,但是它不是一种设计模式,反而比较像是一种编程习惯。那么本篇,我们来看一下,“真正的”工厂模式之工厂方法模式。
工厂方法模式属于创建型模式,它定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类,

工厂方法包含如下几个角色:
  • 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

工厂方法模式结构

image.png

重构一下简单工厂的示例就如下所示:

image.png

工厂方法模式重构代码

为了提高代码扩展性,我们需要将简单工厂中的if分支逻辑去掉,通过增加抽象工厂(生产工厂的工厂)的方式,让具体工厂去进行实现,由具体工厂来决定实例化哪一个具体的产品对象。比如宝马汽车下,会有3系、5系、7系等等。

CarFactory

抽象工厂
/**
 * @author Duansg
 * @date 2022-12-15 12:12 上午
 */
public interface CarFactory {

    /**
     *
     * @param carName
     * @param userName
     * @return
     */
    Response<CarInfo> getCar(String userName);

}

AudiCarFactory

具体工厂
/**
 * @author Duansg
 * @date 2022-12-17 1:46 上午
 */
public class AudiCarFactory implements CarFactory {

    @Override
    public Response<CarInfo> getCar(String userName) {
        return new AudiCar().sendCars(userName);
    }
}

BenzCarFactory

具体工厂
/**
 * @author Duansg
 * @date 2022-12-15 12:13 上午
 */
public class BenzCarFactory implements CarFactory  {

    @Override
    public Response<CarInfo> getCar(String userName) {
        return new BenzCar().sendCars(userName);
    }
}

BmwCarFactory

具体工厂
/**
 * @author Duansg
 * @date 2022-12-15 12:22 上午
 */
public class BmwFactory implements CarFactory {

    @Override
    public Response<CarInfo> getCar(String userName) {
        return new BmwCar().sendCars(userName);
    }
}

Test Controller V1

但是通过上面代码,不难看出,我们要利用抽象工厂的能力,但是这些工厂类对象的创建逻辑又耦合进了逻辑方法中,跟我们简单工厂非常相似,只不过多封装了一层,所以引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了。

@RequestMapping(value = "/getCarInfo", method = RequestMethod.GET)
public Response<CarInfo> getCarInfo(String carName, String userName) {
        CarFactory carFactory = null;
        switch (carName) {
            case "宝马汽车":
                carFactory = new BmwFactory();
                break;
            case "奔驰汽车":
                carFactory = new BenzCarFactory();
                break;
            case "奥迪汽车":
                carFactory = new AudiCarFactory();
                break;
        }
       
        if (ObjectUtils.isEmpty(carFactory)) {
            return Response.failOfMessage("异常");
        }
        return carFactory.getCar(userName);
}
那怎么来解决这个问题呢?

可以为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。

/**
 * @author Duansg
 * @date 2022-12-15 12:36 上午
 */
public class CommonCarFactory {

    private static final Map<String, CarFactory> CACHED_FACTORIES = new HashMap<>();

    static{
        CACHED_FACTORIES.put("宝马汽车", new BmwFactory());
        CACHED_FACTORIES.put("奔驰汽车",new BenzCarFactory());
        CACHED_FACTORIES.put("奥迪汽车", new BenzCarFactory());
    }

    public static Response<CarInfo> getCar(String carName, String userName) {
        return CACHED_FACTORIES.get(carName).getCar(userName);
    }
}

Test Controller V2

那么优化过的代码如下:
@RequestMapping(value = "/getCarInfo", method = RequestMethod.GET)
public Response<CarInfo> getCarInfo(String carName, String userName) {
    return CommonCarFactory.getCar(carName, userName);
}

现在我们的代码已经基本上符合了开闭原则,当新增一个新的汽车产品时,我们需要做的事情包括如下:

  • 创建新的产品类,并且让该产品实现抽象产品接口。
  • 创建产品类对应的具体工厂,并让具体工厂实现抽象工厂。
  • 将新的具体工厂对象,添加到CommonCarFactory的CACHED_FACTORIES中即可,对原本类的侵入很少,只需要在静态代码块中新增一行代码,需要改动的代码改动的非常少。

我们什么时候使用工厂方法模式?

  • 需要使用很多重复代码创建对象时,比如,Dao层的数据对象、API层的Vo对象等。
  • 创建对象要访问外部信息或资源时,比如,读取数据库字段,获取访问授权token信息,配置文件等。
  • 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
  • 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。这些对象的特性是:有限、可重用,使用工厂方法模式可以有效节约资源。
  • 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等。

小结

我们通过一个简单的示例来认识了工厂方法模式,我们也不难总结出如下:
优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
  • 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。
目录
相关文章
|
设计模式 Linux 开发者
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)也是一种创建型设计模式,它提供了一种方式,可以创建一系列相互关联或相互依赖的对象,而不需要指定它们的具体类。
97 1
|
设计模式
设计模式5 - 工厂方法模式【Factory Method Pattern】
设计模式5 - 工厂方法模式【Factory Method Pattern】
38 0
|
设计模式 Java 数据库连接
工厂模式(Factory Pattern)
工厂模式(Factory Pattern)是一种常用的设计模式,它提供了一种创建对象的方式,可以根据不同的需求,动态地创建不同类型的对象。
84 1
|
设计模式 Java
工厂模式(Factory Pattern)(三)
工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的绝佳方式。
122 2
工厂模式(Factory Pattern)(三)
|
设计模式 Java
工厂模式(Factory Pattern)(一)
工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的绝佳方式。
112 1
工厂模式(Factory Pattern)(一)
|
设计模式 XML Java
Java设计模式-工厂模式(FactoryPattern)
Java设计模式-工厂模式(FactoryPattern)
|
存储 设计模式 Java
创建型模式 - 工厂模式(Factory Pattern)
创建型模式 - 工厂模式(Factory Pattern)
|
设计模式 数据库
【愚公系列】2021年12月 二十三种设计模式(一)-工厂方法模式(Factory Method Pattern)
【愚公系列】2021年12月 二十三种设计模式(一)-工厂方法模式(Factory Method Pattern)
【愚公系列】2021年12月 二十三种设计模式(一)-工厂方法模式(Factory Method Pattern)
|
C# 设计模式 .NET
使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)
本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子.   前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是接口(interface).
1449 0