设计模式之工厂模式

71 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

前戏

作为小宅男,我很喜欢吃ls薯片,而我们都知道这些薯片都是ls的工厂批量生产的,我们想吃直接去商店买就行了,很是方便。我们设想一下,如果没有这些工厂,我们想吃薯片,是不是就要自己做,而做薯片那么多步骤,那么复杂,是不是感觉都要世界末日了。。。

正片

既然做薯片这么麻烦,我们就将这做薯片的任务交给工厂吧

我们程序中工厂模式分为

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂模式,也叫静态工厂模式。没增加一个产品就需要增加一个产品类和修改原来的工厂类,不符合开闭原则。

我们先来创建一个Car的抽象类,两个Car的实现类

interface Car{

    void drive();
}

class ModelY implements Car{

    private String name;

    public ModelY(String name) {
        this.name = name;
    }

    @Override
    public void drive() {
        System.out.println("驾驶" + name);
    }
}

class ModelX implements Car{

    private String name;

    public ModelX(String name) {
        this.name = name;
    }

    @Override
    public void drive() {
        System.out.println("驾驶" + name);
    }
}

在来写一个创建Car的普通工厂类

class TeslaSimpleFactory{

    public static Car buildCar(String name){
        Car car = null;
        switch (name){
            case "ModelY":
                car = new ModelY(name);
                break;
            case "ModelX":
                car = new ModelX(name);
                break;
        }
        return car;
    }
}

我们只需要传入要生成Car的名字,就能创建相应的对象

public static void main(String[] args) {
    // 普通工厂模式
    System.out.println("=============普通工厂模式 start==========");
    Car modelX = TeslaSimpleFactory.buildCar("ModelX");
    modelX.drive();
    Car ModelY = TeslaSimpleFactory.buildCar("ModelY");
    ModelY.drive();
}

image.png

是不是很简单,就是一个创建对象的静态方法。

那我们来分析一下,他的优点及缺点

优点

  • 第一点也是工厂模式的共性:工厂和产品指责分工明确
  • 客户端不需要关心产品的创建过程,只需要提供相应的参数交给工厂创建

缺点

  • 工厂类单一,负责的职责却很重,不利于系统的维护
  • 系统拓展困难,不符合开闭原则

当然,简单工厂模式也是有他的应用场景的

应用场景

当需要创建的产品对象种类较少,并且创建对象的过程比较简单的时候,可以使用简单工厂模式

工厂方法模式

工厂方法模式为了解决简单工厂模式违背开闭原则的问题,增加了一个抽象工厂类,每一个需要创建的对象都需要创建一个抽象工厂的实现工厂,我们来看代码

先来创建一个抽象工厂,有一个生产Car的方法

interface MethodFactory{

    Car buildCar();
}

如果公司需要生产两个产品:ModelX,ModelX;这时候就需要分别实现抽象工厂

class ModelXFactory implements MethodFactory{

    @Override
    public Car buildCar() {
        return new ModelX("ModelX");
    }
}

class ModelYFactory implements MethodFactory{

    @Override
    public Car buildCar() {
        return new ModelY("ModelY");
    }
}

写个main方法测试一下

public static void main(String[] args) {
    // 工厂方法模式
    System.out.println("=============工厂方法模式 start==========");
    ModelXFactory modelXFactory = new ModelXFactory();
    modelXFactory.buildCar().drive();
    ModelYFactory modelYFactory = new ModelYFactory();
    modelYFactory.buildCar().drive();
}

image.png

优点

  • 无须关心对象的创建过程
  • 拓展性增强,增加一个产品,只需要增加一个相应的工厂类,不需要改代码

缺点

  • 工厂类的数量容易过多,增加系统复杂度
  • 增加系统的抽象度和理解难度
  • 一个工厂类只能生产一个产品

抽象工厂模式

我们知道了工厂方法有一个缺点:就是一个类只能生产一个产品,可能会导致系统的类数量过多,造成系统复杂度提高,那么抽象工厂模式就能完美的解决

我们先来定义一个抽象工厂,提供了两个方法,分别生产不同的产品,但是这两个产品属于一个产品组

interface AbstractFactory{

    Car buildModelY();

    Car buildModelX();
}

然后我们再创建一个具体的工厂实现

class ConcreteCarFactory implements AbstractFactory{

    @Override
    public Car buildModelY() {
        return new ModelY("ModelY");
    }

    @Override
    public Car buildModelX() {
        return new ModelX("ModelX");
    }
}

main方法测试一下

public static void main(String[] args) {
    // 抽象工厂模式
    System.out.println("=============抽象工厂模式 start==========");
    AbstractFactory factory = new ConcreteCarFactory();
    factory.buildModelX().drive();
    factory.buildModelY().drive();
}

image.png

优点

  • 解决了工厂方法模式的问题
  • 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
  • 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。

缺点

当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。

应用场景

  1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

注意点

抽象工厂模式是将一系列相互关联或相互依赖的产品的生产放在一个抽象工厂类中,他们属于同一个产品组;如果两个产品是相互独立,毫无关系就应该重新创建一个抽象工厂类。

结尾

其实,这三种工厂模式都是逐步优化递进的。简单工厂模式适合产品种类较少的,工厂方法模式解决了简单工厂模式的扩展性差的问题,抽象工厂模式解决了产品种类多导致工厂类数量容易过多的问题,但是他们各自也有他各自的应用场景,需要根据实际业务分析。