Factory mode of creation mode

1 Overview

The creation pattern provides a best practice for creating objects. The core idea of factory method pattern is to get objects through unified factory classes without calling the class's constructor.

2 advantages

  1. You can delay the instantiation of a class to a subclass. The caller does not need to know what the concrete implementation of the interface / abstract class is. The instance of the class can be obtained by using the factory method to reduce the coupling with the caller.
  2. Hide the construction details of the class, reduce the complexity of class creation, and improve the readability of the program.
  3. Different methods can be constructed from the factory according to different environments / parameters.

3 cases

There's a hotel interface. There are cooks and waiters in the hotel. We define KFC and PizzaHut as two hotels:

interface Restaurant {
    void getCook();
    void getWaiter();
}

public class KFC implements Restaurant {

    [@Override](https://my.oschina.net/u/1162528)
    public void getCook() {
        System.out.println("I'm KFC cook.");
    }

    [@Override](https://my.oschina.net/u/1162528)
    public void getWaiter() {
        System.out.println("I'm KFC waiter.");
    }
}

class PizzaHut implements Restaurant {

    [@Override](https://my.oschina.net/u/1162528)
    public void getCook() {
        System.out.println("I'm PizzaHut cook.");
    }

    [@Override](https://my.oschina.net/u/1162528)
    public void getWaiter() {
        System.out.println("I'm PizzaHut waiter.");
    }
}

3.1 plant type 1

Define another factory method, RestaurantFactory. From the factory, you can easily get the corresponding hotel according to the type:

public class Test {
    public static void main(String[] args) {
        RestaurantFactory factory = new RestaurantFactory();
        Restaurant kfc = factory.createRestaurant(RestaurantFactory.RestaurantType.KFC);
        Restaurant pizzaHut = factory.createRestaurant(RestaurantFactory.RestaurantType.PizzaHut);
        kfc.getCook();
        pizzaHut.getWaiter();
    }
}

class RestaurantFactory {
    enum RestaurantType {
        KFC, PizzaHut
    }

    Restaurant createRestaurant(RestaurantType type) {
        switch (type) {
            case KFC: return new KFC();
            case PizzaHut: return new PizzaHut();
            default: System.out.format("Invalid restaurant %s", type); return null;
        }
    }
}

Output:

I'm KFC cook.
I'm PizzaHut waiter.

For example, in Spring BeanFactory This is the pattern used: the getBean method takes the Bean's type / name as a parameter and returns the corresponding Bean. The Calendar class in JDK also uses this mode:

public static Calendar getInstance(TimeZone zone, Locale aLocale) {
    ...
    // Create different Calendar instances based on parameters
    if (aLocale.hasExtensions()) {
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
            switch (caltype) {
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }
    ...
}

If the instance type is relatively fixed, the above pattern can meet the requirements well. However, if the instance type is uncertain, the original method needs to be changed whenever a new type needs to be added, and the opening and closing principles are not well followed. So there's a second type.

3.2 plant type 2

It's still an example of a hotel. We define a factory as follows:

public class Test {
    public static void main(String[] args) {
        KFCFactory kfcFactory = new KFCFactory();
        PizzaHutFactory pizzaHutFactory = new PizzaHutFactory();
        Restaurant kfc = kfcFactory.createRestaurant();
        Restaurant pizzaHut = pizzaHutFactory.createRestaurant();
        kfc.getCook();
        pizzaHut.getWaiter();
    }
}

class KFCFactory {
    Restaurant createRestaurant() {
        return new KFC();
    }
}

class PizzaHutFactory {
    Restaurant createRestaurant() {
        return new PizzaHut();
    }
}

Output:

I'm KFC cook.
I'm PizzaHut waiter.

In the above method, for each new category, you only need to add a corresponding factory. The original factory method and instance do not need to be modified. as LoggerFactory It's this type of factory model:

public static Logger getLogger(String name) {
    // getLogger is ultimately delegated to ILoggerFactory.
    // To add a new Logger acquisition method, you only need to add an implementation class of ILoggerFactory, which is highly extensible.
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
}

But in this way, for each category, there should be a factory class, which has a relatively high complexity. In practice, the first type is frequently used.

4 Summary

Factory method pattern is a widely used creation pattern, which can be seen in almost all open source frameworks. Typically, the factory class ends with the word factory: -).

The github address of the example in this paper

Tags: Programming Spring JDK github

Posted on Fri, 20 Mar 2020 11:40:20 -0400 by sneamia