The factory pattern

The factory pattern is one of our most common design patterns, using the factory method instead of the New operation. Factory patterns are divided into three categories: simple factory, factory method and abstract factory.

Simple factory

Define a factory class that determines which class to instantiate based on the arguments passed in:

public interface Mouse {
    void sayHello(a);
}
public class DellMouse implements Mouse {
    @Override
    public void sayHello(a) {
        System.out.println("Hello, I'm Dale Mouse."); }}public class LenovoMouse implements Mouse {
    @Override
    public void sayHello(a) {
        System.out.println("Hello, I'm Lenovo Mouse."); }}// Mouse factory class, responsible for creating mouse instances
public class MouseFactory {

    public static Mouse createMouse(int type){
        switch (type){
            case 1:
                return new DellMouse();
            case 2:
                return new LenovoMouse();
            default:
                return null; }}}Copy the code

Here’s a quick test:

public static void main(String[] args) {
        Mouse dell = MouseFactory.createMouse(1);
        dell.sayHello();
        Mouse lenovo = MouseFactory.createMouse(2);
        lenovo.sayHello();
 }
Copy the code

Console output:

Hello, I’m Dell Mouse Hello, I’m Lenovo mouse

You can see that the MouseFactory factory class can decide which Mouse implementation class to instantiate based on the type passed in.

advantages

Mask the process of creating the object and mask the details from the client.

disadvantages

The disadvantages are also obvious. If the process of creating an object is not simply new LenovoMouse() or New DellMouse() but a large chunk of initialization logic, or if there are too many subclasses of Mouse, the createMouse method in a simple factory can become very bloated. And adding or removing the corresponding Mouse subclasses required modifying the factory code, violating the open and close principle.

The factory method

The factory method is an update on the simple factory, extending the factory class downward and leaving the logic of creating objects to concrete subclass factories.

Add three classes while the Mouse interface and its two subclasses LenovoMouse and DellMouse remain unchanged:

// Factory interface, create logic to specific subclasses to do
public interface MouseFactory {
    Mouse createMouse(a);
}

public class LenovoMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse(a) {
        return newLenovoMouse(); }}public class DellMouseFactory implements MouseFactory {
    @Override
    public Mouse createMouse(a) {
        return newDellMouse(); }}Copy the code

Continue the class to test the result:

public static void main(String[] args) {

    MouseFactory dellMouseFactory = new DellMouseFactory();
    Mouse dellMouse = dellMouseFactory.createMouse();
    dellMouse.sayHello();
    MouseFactory lenovoFactory = new LenovoMouseFactory();
    Mouse lenovoMouse = lenovoFactory.createMouse();
    lenovoMouse.sayHello();

}
Copy the code

Console output: Hello, I’m Dell Mouse Hello, I’m Lenovo mouse

advantages

On the basis of the advantages of simple factory, factory method has been upgraded, in line with the open and closed principle, single responsibility principle, for example, to add a Mouse subclass, then only need to add a factory subclass to create the corresponding Mouse subclass, do not need to change the factory interface, and each factory is responsible for creating only one instance.

disadvantages

Each time you add a subclass of Mouse, you need to add a factory class, and the classes in your project become very numerous.

Furthermore, the factory can only create one type of product creation. If we need to create a series of products, such as A mouse and a keyboard, the factory method pattern cannot do this.

The abstract factory

Then, based on the factory method, abstract method pattern is derived. Abstract factories provide interfaces to create a series of related or interdependent objects.

Again, the Mouse interface and its two subclasses LenovoMouse and DellMouse remain unchanged

// Keyboard instance interface
public interface Keyboard {
    void sayHello(a);
}
// Lenovo keyboard
public class LenovoKeyboard implements Keyboard {
    @Override
    public void sayHello(a) {
        System.out.println("Hello, I'm Lenovo Keyboard."); }}// Dell keyboard
public class DellKeyboard implements Keyboard {
    @Override
    public void sayHello(a) {
        System.out.println("Hi, I'm Dell Keyboard."); }}// The factory that produces mouse and keyboard
public interface ComputerFactory {
    /** * Create mouse instance *@return* /
    Mouse createMouse(a);
    /** * Create a keyboard instance *@return* /
    Keyboard createKeyboard(a);
}
// Lenovo mouse and keyboard factory
public class LenovoComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse(a) {
        return new LenovoMouse();
    }

    @Override
    public Keyboard createKeyboard(a) {
        return newLenovoKeyboard(); }}// Dell Mouse and keyboard Factory
public class DellComputerFactory implements ComputerFactory {
    @Override
    public Mouse createMouse(a) {
        return new DellMouse();
    }

    @Override
    public Keyboard createKeyboard(a) {
        return newDellKeyboard(); }}Copy the code

Continue testing:

public static void main(String[] args) {

    ComputerFactory lenovoComputerFactory = new LenovoComputerFactory();
    Keyboard lenovoKeyboard = lenovoComputerFactory.createKeyboard();
    lenovoKeyboard.sayHello();
    Mouse lenovoMouse = lenovoComputerFactory.createMouse();
    lenovoMouse.sayHello();

    ComputerFactory dellComputerFactory = new DellComputerFactory();
    Mouse dellMouse = dellComputerFactory.createMouse();
    dellMouse.sayHello();
    Keyboard dellKeyboard = dellComputerFactory.createKeyboard();
    dellKeyboard.sayHello();
}
Copy the code

Console output: Hello, I am Lenovo keyboard hello, I am Lenovo mouse hello, I am Dell mouse hello, I am Dell keyboard

advantages

In addition to the advantages of the factory method, the abstract factory can create product families, which solves the disadvantage of the factory method to only support the production of one product.

disadvantages

Abstract factories still have the disadvantages of the factory method. When it is extended, there are too many classes and the relationship is responsible. In addition, when extending a product, the specific factory production interface needs to be modified, which violates the open and closed principle.

conclusion

Abstract factories: Each abstract product is derived from multiple concrete product classes, each abstract factory class is derived from multiple concrete factory classes, each concrete factory class is responsible for the creation of a series of concrete products

Factory method: Each abstract product is derived from multiple concrete product classes, each abstract factory class is derived from multiple concrete factory classes, each concrete factory class is responsible for the creation of a concrete product

You can choose the appropriate factory pattern for different scenarios