Factory Method

1. Model definition

Define an interface for creating objects and let subclasses decide which class to instantiate. The Factory Method causes the instantiation of a class to be deferred to subclasses

Class diagram:

Application scenarios

  • When you don’t know the exact type of object you’re using
  • When you want to provide a library or framework with a way to extend its internal components

advantages

  • Decouple the specific product from the creator
  • Consistent with the principle of single responsibility
  • In line with the open and close principle

Application in source code

// Factory method
// java.net.URLStreamHandleFactory
public interface URLStreamHandlerFactory {
    /**
     * Creates a new {@code URLStreamHandler} instance with the specified
     * protocol.
     *
     * @param   protocol   the protocol ("{@code ftp}",
     *                     "{@code http}", "{@code nntp}", etc.).
     * @return  a {@code URLStreamHandler} for the specific protocol.
     * @see     java.net.URLStreamHandler
     */
    URLStreamHandler createURLStreamHandler(String protocol);
}
// Subclass implementation
private static class Factory implements URLStreamHandlerFactory {
    private static String PREFIX = "sun.net.www.protocol";

    private Factory(a) {}public URLStreamHandler createURLStreamHandler(String var1) {
        String var2 = PREFIX + "." + var1 + ".Handler";

        try {
            Class var3 = Class.forName(var2);
            return (URLStreamHandler)var3.newInstance();
        } catch (ReflectiveOperationException var4) {
            throw new InternalError("could not load " + var1 + "system protocol handler", var4); }}}Copy the code

2. Code refactoring

Original code:

public class FactoryMethod {
    public static void main(String[] args) {
        Application application = newApplication(); ProductA product = application.getObject(); product.method1(); }}class ProductA {
    public void method1(a) {
        System.out.println("ProductA==>method1==>executed"); }}class Application {
    private ProductA createProduct(a) {
        return new ProductA();
    }

    ProductA getObject(a) {
        ProductA product = createProduct();
        returnproduct; }}Copy the code
  1. The stable parts of a class are separated and encapsulated into abstract interfaces
interface Product {
    /** * abstract method */
    public void method1(a);
}
class ProductA implements Product{
    @Override
    public void method1(a) {
        System.out.println("ProductA==>method1==>executed"); }}Copy the code

The corresponding interface class can be used to receive:

class Application {
    private Product createProduct(a) {
        return new ProductA();
    }

    Product getObject(a) {
        Product product = createProduct();
        returnproduct; }}Copy the code

Disadvantages: You can’t avoid new concrete classes when creating objects

  1. Simple factory

Not a design pattern, just a coding trick

Create a class that creates different objects with different parameters:

class SimpleFactory {
    public static Product createProduct(String type) {
        if (type.equals("0")) {
            return new ProductA();
        } else if ("1".equals(type)){
            return new ProductB();
        } else {
            return null; }}}Copy the code

In this way, we can control the creation of objects by using parameters, and the code will not write a specific new class:

class Application {
    private Product createProduct(String type) {
        return SimpleFactory.createProduct(type);
    }

    Product getObject(String type) {
        Product product = createProduct(type);
        returnproduct; }}Copy the code
  1. The factory pattern

Turn the application into an abstract class, turning the actual method you create into an abstract method, and letting the user implement it in a subclass.

abstract class Application {
    /** * abstract method *@return* /
    abstract Product createProduct(a);

    Product getObject(a) {
        Product product = createProduct();
        returnproduct; }}Copy the code

Subclass implementation:

class ConcreateProductA extends Application {

    @Override
    Product createProduct(a) {
        return newProductA(); }}class ConcreateProductB extends Application {

    @Override
    Product createProduct(a) {
        return newProductB(); }}Copy the code

Specific use:

public class FactoryMethod {
    public static void main(String[] args) {
        Application application = newConcreateProductB(); Product product = application.getObject(); product.method1(); }}Copy the code

3. Overall code

public class FactoryMethod {
    public static void main(String[] args) {
        Application application = newConcreateProductB(); Product product = application.getObject(); product.method1(); }}interface Product {
    /** * abstract method */
    public void method1(a);
}
class ProductA implements Product{
    @Override
    public void method1(a) {
        System.out.println("ProductA==>method1==>executed"); }}class ProductB implements Product{
    @Override
    public void method1(a) {
        System.out.println("ProductB==>method1==>executed"); }}abstract class Application {
    /** * abstract method *@return* /
    abstract Product createProduct(a);

    Product getObject(a) {
        Product product = createProduct();
        returnproduct; }}class ConcreateProductA extends Application {

    @Override
    Product createProduct(a) {
        return newProductA(); }}class ConcreateProductB extends Application {

    @Override
    Product createProduct(a) {
        return newProductB(); }}Copy the code