Abstract Factory Mode for Creative Mode

1 Overview

Last article Speaking of the factory method pattern, it provides a solution for creating class instances without specifying a specific implementation.So why do we need the abstract factory model?

2 Abstract Factory Mode

The abstract factory model is essentially also a factory defined as an entry for class creation, which has the advantages of the factory method pattern: hiding class construction details, reducing class usage complexity, decoupling from callers, and so on. The biggest difference between the abstract factory mode and the factory method mode is that it emphasizes the creation of a family of elements.For example, for different browsers, there are different buttons, selection boxes and input boxes.Then we can define a browser's interface and create a browser factory, ChromeFactory, FirefoxFactory.Among them, ChromeFactory can create buttons, selection boxes of the Chrome family, and FirefoxFactory can create button selection boxes of the Firefox family, which can achieve high cohesion of elements of the same family and improve the flexibility and scalability of the program.

3 Cases

Take another simple example.There is a car factory that can produce cars and SUV s.

interface CarFactory {
    Car getCar();
    SUV getSUV();
}

interface Car {
    void getSize();
}

interface SUV {
    void getSize();
}

By category, factories can also be divided into American factories and Japanese factories.Japanese factories can only produce Japanese cars, while American factories can only produce American cars. This is a binding relationship:

class AmericanCarFactory implements CarFactory {
    [@Override](https://my.oschina.net/u/1162528)
    public Car getCar() {
        return new TeslaModalS();
    }
    [@Override](https://my.oschina.net/u/1162528)
    public SUV getSUV() {
        return new TeslaModalX();
    }
}
public class TeslaModalS implements Car {
    [@Override](https://my.oschina.net/u/1162528)
    public void getSize() {
        System.out.println("Size of American Car Modal S is '4979*1964*1445'");
    }
}
public class TeslaModalX implements SUV {
    [@Override](https://my.oschina.net/u/1162528)
    public void getSize() {
        System.out.println("Size of American SUV Modal X is '5037*2070*1684'");
    }
}

class JapaneseCarFactory implements CarFactory {
    [@Override](https://my.oschina.net/u/1162528)
    public Car getCar() {
        return new HondaAccord();
    }
    @Override
    public SUV getSUV() {
        return new HondaCRV();
    }
}
public class HondaAccord implements Car {
    @Override
    public void getSize() {
        System.out.println("Size of Japanese Car Accord is '4893*1862*1449'");
    }
}
public class HondaCRV implements SUV {
    @Override
    public void getSize() {
        System.out.println("Size of Japanese SUV C-RV is '4585*1855*1689'");
    }
}

After defining the above factories, we limit the products of the same family to the corresponding factories.Then, by defining a unified entrance, you can easily create a car:

public class Test {
    public static void main(String[] args) throws OperationNotSupportedException {
        CarFactory japaneseCarFactory = CarFactoryProducer.createFactory(CarFactoryProducer.FactoryType.JAPANESE);
        Car japaneseCar = japaneseCarFactory.getCar();
        japaneseCar.getSize();
        SUV japaneseSUV = japaneseCarFactory.getSUV();
        japaneseSUV.getSize();

        CarFactory americanCarFactory = CarFactoryProducer.createFactory(CarFactoryProducer.FactoryType.AMERICAN);
        Car americanCar = americanCarFactory.getCar();
        americanCar.getSize();
        SUV americanSUV = americanCarFactory.getSUV();
        americanSUV.getSize();
    }
}

public abstract class CarFactoryProducer {
    enum FactoryType {
        JAPANESE, AMERICAN
    }

    public static CarFactory createFactory(FactoryType type) throws OperationNotSupportedException {
        switch (type) {
            case JAPANESE: return new JapaneseCarFactory();
            case AMERICAN: return new AmericanCarFactory();
        }
        throw new OperationNotSupportedException("type '" + type + "' is not supported");
    }
}

Output:

Size of Japanese Car Accord is '4893*1862*1449'
Size of Japanese SUV C-RV is '4585*1855*1689'
Size of American Car Modal S is '4979*1964*1445'
Size of American SUV Modal X is '5037*2070*1684'

UML:

As you can see, the abstract factory pattern greatly reduces the complexity of class creation and use and improves the cohesion of elements of the same family.At the same time, if you need to add a new family of elements such as German cars, just add a new GermanyCarFactory to make German cars, which is very scalable.

In JDK, DocumentBuilderFactory The abstract factory model is used:

public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
        // Returns the corresponding Factory implementation class based on the parameters passed in
        return FactoryFinder.newInstance(DocumentBuilderFactory.class, factoryClassName, classLoader, false);
}

4 Summary

The abstract factory pattern provides the best way to create a class of elements, and the generic factory class ends with Factory, and the creation method returns a child Factory.Consider using abstract factory mode when you need to create a set of classes belonging to a unified category and want to provide a simple interface to the outside world.

The github address of the example in this article

Keywords: Programming Firefox JDK github

Added by bhogg on Sat, 21 Mar 2020 07:53:49 +0200