1. 抽象工厂模式概述

抽象工厂就是工厂的工厂,把工厂抽象成一个产品,那它的工厂就是抽象工厂。

工厂模式用来生产产品,抽象工厂用来生产工厂。

(1) 适用情况

同一个产品族(大类)里面,包含多种产品(小类),每个产品对应一个工厂,那么产品族就对应一个抽象工厂。

(2) 优点

与工厂模式类似:屏蔽创建的具体细节、容易拓展产品

(3) 缺点

扩展产品族困难,要增加一个新产品,需要改动的地方较多

2. 抽象工厂模式实例

我们接着工厂模式中的例子。
我们现在已经拥有了建造汽车的工厂,但是我们还想建造火车怎么办?
这里就可以使用抽象工厂:

(1) 先声明一个火车接口

public interface Train {
    void declare();
}

(2) 创建各个种类的火车

public class HighSpeed implements Train {
    @Override
    public void declare() {
        System.out.println("我是一辆高铁。");
    }
}

public class LowSpeed implements Train {
    @Override
    public void declare() {
        System.out.println("我是一辆慢车。");
    }
}

(3) 声明抽象工厂接口

public interface AbstractFactory {
    // 用来生产汽车
    Car buildCar(CAR_BRAND brand);

    // 用来生产火车
    Train buildTrain(TRAIN_TYPE type);
}

(4) 创建工厂类,实现抽象工厂接口

public class TrainFactory implements AbstractFactory {
    @Override
    public Car buildCar(CAR_BRAND brand) {
        // 火车工厂不能生产汽车
        return null;
    }

    @Override
    public Train buildTrain(TRAIN_TYPE type) {
        switch (type) {
            case HIGH_SPEED:
                return new HighSpeed();
            case LOW_SPEED:
                return new LowSpeed();
            default:
                return null;
        }
    }
}

enum TRAIN_TYPE {
    HIGH_SPEED,
    LOW_SPEED
}

(5) 创建工厂生成类,用来创建工厂

public class FactoryProducer {
    public static AbstractFactory getFactory(String choice) {
        switch (choice) {
            case "Car":
                return new CarFactory();
            case "Train":
                return new TrainFactory();
            default:
                return null;
        }
    }
}

(6) 使用抽象工厂创建汽车和火车

public class FactoryDemo {
    public static void main(String[] args) {
        // 获取汽车工厂
        AbstractFactory carFactory = FactoryProducer.getFactory("Car");
        // 生产奔驰汽车
        Car car = carFactory.buildCar(CAR_BRAND.BENZ);
        car.declare();

        // 获取火车工厂
        AbstractFactory trainFactory = FactoryProducer.getFactory("Train");
        // 生产高铁
        Train train = trainFactory.buildTrain(TRAIN_TYPE.HIGH_SPEED);
        train.declare();
    }
}

运行结果:
image.png

3. 一些思考

对于我们的工厂来说,汽车和火车都是产品,而且都属于交通工具,所以它们都属于一个产品族。

我们声明了AbstractFactory作为抽象工厂接口,但是其实它并不是用来创建工厂的,它只是各个工厂的抽象层。真正用来创建工厂的是FactoryProducer类,也许它才更应该被叫做工厂的工厂。

AbstractFactory中声明了两个方法,分别用来生产汽车和火车,因此在它的实现类TrainFactory中,就得把两个接口都实现,即使它不应该生产汽车,这样不就破坏了接口隔离原则了吗?
个人认为,可以在AbstractFactory中提供buildCar方法的默认实现,然后在TrainFactory中就不必实现这个它根本不关心的方法了。

考虑一下,如果我们要再生产一种产品,比如飞机,需要做出哪些改动?
飞机接口,飞机实现类,飞机工厂,抽象工厂接口、工厂生成类。。。
好像是比直接使用工厂模式要麻烦一些,拓展产品组确实困难了。
再考虑下之前的问题,如果不在AbstractFactory中提供buildAirplain方法的默认实现,那么它所有的实现类(各个工厂)都需要进行改动,这也违反了开闭原则。

参考引用

抽象工厂模式:https://www.runoob.com/design...


Zealf
13 声望1 粉丝