设计模式之工厂方法模式

111 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

简介

工厂模式也是一种很常见的设计模式。简单来说就是把要new的类放到一个统一的类中,这个类就叫做工厂类,它就是一个产生类的工厂。这样由工厂类统一创建同一个类型的类,方便管理和拓展。

但是工厂方法又有好几种,什么简单工厂方法、静态工厂方法、工厂方法、抽象工厂方法。今天咱们就来简单聊一聊。

案例

简单工厂方法

public abstract class Car {
    abstract void drive();
}
public class Benz extends Car {
    @Override
    void drive() {
        System.out.println("奔驰开");
    }
}
public class Bmw extends Car {
    @Override
    void drive() {
        System.out.println("宝马开");
    }
}
public class CarFactory {
    public static Car getCarByType(String type) {
        if (Objects.equals("1", type)) {
            return new Bmw();
        }else if(Objects.equals("2", type)) {
            return new Benz();
        }else {
            return null;
        }
    }
}
public class DriverCar {
    public static void main(String[] args) {
        Car car = CarFactory.getCarByType("1");
        car.drive();
        Car car1 = CarFactory.getCarByType("2");
        car1.drive();
    }
}

如上面的代码,一个抽象的Car,一个宝马一个奔驰分别继承抽象类Car,一个生产车的工厂类CarFactory,然后一个应用的开车类。这样就实现了简单工厂模式。开车的类中通过传入需要获取的车的类型来调用CarFactory,工厂类根据入参类型返回不同类型的车的实现。

这里CarFactory的getCarByType是一个静态方法,所以简单工厂模式也就叫做静态工厂模式。通过简单工厂模式,我们将创建Car的过程统一放到工厂类里面,统一管理。但是如果后续拓展需要增加车的类型,不仅需要增加一个对Car的继承类,还要在工厂类里面修改,增加新增的这个车型的实例返回逻辑。所以这种简单工厂模式虽然抽取了创建车的过程在一个类里,但是并不是符合开闭原则。下面我们将看看工厂方法模式是怎么解决这个问题的。

工厂方法模式

public abstract class Car {
    abstract void drive();
}
public class Benz extends Car{
    @Override
    void drive() {
        System.out.println("奔驰开");
    }
}
public class Bmw extends Car{
    @Override
    void drive() {
        System.out.println("宝马开");
    }
}
public abstract class AbsCarFactory {
    abstract Car produce();
}
public class BenzFactory extends AbsCarFactory {
    @Override
    Car produce() {
        return new Benz();
    }
}
public class BmwFactory extends AbsCarFactory{
    @Override
    Car produce() {
        return new Bmw();
    }
}
public class DriverCar {
    public static void main(String[] args) {
        new BenzFactory().produce().drive();
        new BmwFactory().produce().drive();
    }
}

很明显我们看到工厂方法模式的代码量大大地增加了,相比简单工厂方法模式我们类的数量成倍地增加了。我们看到工厂方法模式在创建Car的工厂类这一层也做了抽象处理,每一个Car均有了自己独立的XXCarFactory,这样的好处是我们不用去通过类型来调用工厂方法了,而是直接在应用层根据需要通过实例化不同Car的工厂方法即可得到对应的工厂,然后再通过该工厂去创建一个我们最终需要的Car。而后续如果需要增加一个新的类型,那么我们可以通过新增一个Car的实现,然后新增一个这个Car的工厂类即可,也满足了开闭原则。

总结

可以看到,虽然工厂方法的的灵活性变得更好了,满足开闭原则,可以随意增加新的类型的车进来,但是一旦新增一个类型的车就要增加2个类,这样在维护上也带来了一定的麻烦,在类的总数量上翻倍,那维护的困难层度上应该也会是翻倍的。因此我们在使用工厂方法是,如果不是特殊要求和场景,不建议都使用工厂方法,一般情况下简单工厂即可满足要求,我们不能为了满足原则而满足,也要考虑代码的简洁和可维护性。