Design pattern - abstract factory pattern

Posted by bow-viper1 on Wed, 08 Dec 2021 19:28:20 +0100

1. Overview of abstract factory pattern

An abstract factory is the factory of a factory. If you abstract a factory into a product, its factory is an abstract factory.

Factory mode is used to produce products, and abstract factory is used to produce factories.

(1) Application

The same product family (category) contains multiple products (subclasses). Each product corresponds to a factory, so the product family corresponds to an abstract factory.

(2) Advantages

Similar to the factory model: shielding the specific details of creation and easy to expand products

(3) Shortcomings

It is difficult to expand the product family. There are many changes to add a new product

2. Abstract factory pattern instance

Let's go on Factory mode Examples in.
We now have a factory to build cars, but what if we still want to build trains?
Here you can use the abstract factory:

(1) First declare a train interface

public interface Train {
    void declare();
}

(2) Create various kinds of trains

public class HighSpeed implements Train {
    @Override
    public void declare() {
        System.out.println("I'm a high-speed train.");
    }
}

public class LowSpeed implements Train {
    @Override
    public void declare() {
        System.out.println("I'm a local train.");
    }
}

(3) Declare abstract factory interface

public interface AbstractFactory {
    // Used to make cars
    Car buildCar(CAR_BRAND brand);

    // Used to produce trains
    Train buildTrain(TRAIN_TYPE type);
}

(4) Create a factory class to implement the abstract factory interface

public class TrainFactory implements AbstractFactory {
    @Override
    public Car buildCar(CAR_BRAND brand) {
        // The train factory cannot produce cars
        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) Create a factory generation class to create a factory

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) Create cars and trains using abstract factories

public class FactoryDemo {
    public static void main(String[] args) {
        // Get auto factory
        AbstractFactory carFactory = FactoryProducer.getFactory("Car");
        // Production of Mercedes Benz cars
        Car car = carFactory.buildCar(CAR_BRAND.BENZ);
        car.declare();

        // Get train factory
        AbstractFactory trainFactory = FactoryProducer.getFactory("Train");
        // Production of high-speed railway
        Train train = trainFactory.buildTrain(TRAIN_TYPE.HIGH_SPEED);
        train.declare();
    }
}

Operation results:

3. Some thoughts

For our factory, cars and trains are products, and they all belong to transportation, so they all belong to a product family.

We declare AbstractFactory as an abstract factory interface, but it is not used to create factories. It is just the abstraction layer of each factory. The FactoryProducer class is really used to create a factory. Maybe it should be called a factory.

AbstractFactory declares two methods, which are respectively used to produce cars and trains. Therefore, in its implementation class TrainFactory, it has to implement both interfaces, even if it should not produce cars. Does this break the interface isolation principle?
Personally, I think that the default implementation of buildCar method can be provided in AbstractFactory, and then there is no need to implement this method that it doesn't care about at all in TrainFactory.

Consider what changes we need to make if we want to produce another product, such as an aircraft?
Aircraft interface, aircraft implementation class, aircraft factory, abstract factory interface, factory generation class...
It seems to be more troublesome than using the factory model directly. It is really difficult to expand the product group.
Consider the previous problem again. If you do not provide the default implementation of buildeairplan method in AbstractFactory, all its implementation classes (each factory) need to be changed, which also violates the opening and closing principle.

Reference reference

Abstract factory pattern: https://www.runoob.com/design...

Topics: Design Pattern