Detailed Explanation of Factory Model [01] [01] [01]

Articles Catalogue

1. Simple Factory Model

An instance of a product class created by a factory object

1.1 Code Implementation

1.1.1 Product abstract class

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public interface ICourse {
    /**
     * Recorded courses
     */
    void record();
}

1.1.2 Specific product categories

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public class JavaCourse implements ICourse {
    /**
     * Recording java courses
     */
    @Override
    public void record() {
        System.out.println("Recording in progress java curriculum");
    }
}

1.1.3 Simple Factory Class

package com.zhunongyun.toalibaba.designpatterns.factory.simplefactory;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;
import com.zhunongyun.toalibaba.designpatterns.factory.common.JavaCourse;
import org.apache.commons.lang3.StringUtils;

public class CourseFactory {

    /**
     * Create objects by name
     * @param name
     * @return
     */
    public ICourse createByName(String name) {
         if ("java".equals(name)) {
             return new JavaCourse();
         } else {
             return null;
         }
    }

    /**
     * Creating objects through class paths
     * @param classPath
     * @return
     */
    public ICourse createByClassPath(String classPath) {
        try {
            if (StringUtils.isNotBlank(classPath)) {
                return (ICourse) Class.forName(classPath).newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Creating objects through classes
     * @param className
     * @return
     */
    public ICourse createByClass(Class className) {
        try {
            if (null != className) {
                return (ICourse) className.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

1.1.4 Test Class

package com.zhunongyun.toalibaba.designpatterns.factory.simplefactory;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;
import com.zhunongyun.toalibaba.designpatterns.factory.common.JavaCourse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;

public class SimelpFactoryTest {

    public static void main(String[] args) {
        CourseFactory courseFactory = new CourseFactory();

        // Create objects by class name
        ICourse nameCourse = courseFactory.createByName("java");
        nameCourse.record();

        // Creating objects through class paths
        ICourse classNameCourse = courseFactory.createByClassPath("com.zhunongyun.toalibaba.designpatterns.factorypattern.common.JavaCourse");
        classNameCourse.record();

        // Creating objects through classes
        ICourse classCourse = courseFactory.createByClass(JavaCourse.class);
        classCourse.record();

        Calendar calendar = Calendar.getInstance();
        Logger logger = LoggerFactory.getLogger("");
    }
}

1.2 Applicable Scenarios

  • Factory classes are responsible for creating fewer objects
  • Clients only need to pass in parameters to factory classes, and they don't need to care about the logic of how to create objects.

1.3 Advantages/Disadvantages

Advantages of 1.3.1

  • You just need to pass in a correct parameter to get the object you need without knowing the details of its creation.

1.3.2 Disadvantage

  • The responsibility of factory class is relatively heavy. When adding new products, it is necessary to modify the judgment logic of factory class, which violates the principle of opening and closing.
  • Difficult to expand over-complex product structure

1.4 Source Code Analysis

Calendar under 1.4.1 java.util

Calendar is a calendar tool that creates the entity class Calendar calendar = Calendar.getInstance() using a simple factory pattern.

Calendar's getInstance() code creates Calendar objects in a simple factory way

public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
    public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
    
    ......
    
    private static Calendar createCalendar(TimeZone zone, Locale aLocale)
    {
        CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        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 (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }
}

LoggerFactory under 1.4.2 org.slf4j

LoggerFactory is a log factory class that creates the object Logger logger = LoggerFactory.getLogger("xx") through a simple factory.

The code for getLogger() of LoggerFactory is to create Logger objects in a simple factory way.

public final class LoggerFactory {
    public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }

    public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName()));
                Util.report("See http://www.slf4j.org/codes.html#loggerNameMismatch for an explanation");
            }
        }
        return logger;
    }
}

2. Factory Method Model

Specifies an interface for creating objects, but lets the class that implements the interface decide which class to instantiate, and the factory method postpones the instantiation of the class to a subclass.

2.1 Code Implementation

2.1.1 Product abstract class

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public interface ICourse {
    /**
     * Recorded courses
     */
    void record();
}

2.1.2 Specific product categories

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public class JavaCourse implements ICourse {
    /**
     * Recording java courses
     */
    @Override
    public void record() {
        System.out.println("Recording in progress java curriculum");
    }
}

2.1.3 Factory Interface Class for Creating Objects

package com.zhunongyun.toalibaba.designpatterns.factory.factorymethod;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;

public interface ICourseFactory {
    /**
     * Create entity classes
     * @return
     */
    ICourse create();
}

2.1.4 Specific Product Factory Category

package com.zhunongyun.toalibaba.designpatterns.factory.factorymethod;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;
import com.zhunongyun.toalibaba.designpatterns.factory.common.JavaCourse;

public class JavaCourseFactory implements ICourseFactory {
    /**
     * Creating java curriculum entity class
     * @return
     */
    @Override
    public ICourse create() {
        return new JavaCourse();
    }
}

2.1.5 Test Class

package com.zhunongyun.toalibaba.designpatterns.factory.factorymethod;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;

public class FactoryMethodTest {
    public static void main(String[] args) {
        ICourseFactory courseFactory = new JavaCourseFactory();

        ICourse course = courseFactory.create();

        course.record();
    }
}

2.2 Applicable Scenarios

  • Creating objects requires a lot of repetitive code
  • Client (application layer) does not depend on details such as how product class instances are created, implemented, etc.
  • A class specifies which object to create through its subclasses

2.3 Advantages/Disadvantages

2.3.1 Advantages

  • Users only need to care about the factories corresponding to the products they need, not about the details of creating them.
  • Adding new products accords with the principle of opening and closing, and improves the expansibility of the system.

2.3.2 Disadvantage

  • The number of classes is easily too many, which increases the complexity of the code structure.
  • It increases the abstraction of the system and the difficulty of understanding.

2.4 Source Code Analysis

LoggerFactory under 2.4.1 org.slf4j

In the code of getLogger() of LoggerFactory, ILoggerFactory iLoggerFactory = getILoggerFactory(); create a specific Logger factory class through the factory method pattern

public final class LoggerFactory {
    public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }
    
    public static ILoggerFactory getILoggerFactory() {
        if (INITIALIZATION_STATE == 0) {
            Class var0 = LoggerFactory.class;
            synchronized(LoggerFactory.class) {
                if (INITIALIZATION_STATE == 0) {
                    INITIALIZATION_STATE = 1;
                    performInitialization();
                }
            }
        }

        switch(INITIALIZATION_STATE) {
        case 1:
            return SUBST_FACTORY;
        case 2:
            throw new IllegalStateException("org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also http://www.slf4j.org/codes.html#unsuccessfulInit");
        case 3:
            return StaticLoggerBinder.getSingleton().getLoggerFactory();
        case 4:
            return NOP_FALLBACK_FACTORY;
        default:
            throw new IllegalStateException("Unreachable code");
        }
    }
}

3. Abstract Factory Model

Providing an interface to create a series of related or interdependent objects without specifying their specific classes

3.1 Product Grade and Family

[Img-itoph8pZ-1566651509510 (evernotecid://DE37D598-33A4-4708-800A-6D4CF841DDE2/wwevernotecom/149352153/ENResource/p275)]

  • Product hierarchy structure: product hierarchy structure is the inheritance structure of products. For example, an abstract class is mobile phone, and its subclasses are Huawei mobile phone, millet mobile phone and Apple mobile phone. Then the abstract mobile phone and the specific brand mobile phone constitute a product hierarchy structure. The Abstract mobile phone is the parent class, and the specific brand mobile phone is its subclass.

  • Product family: In the abstract factory model, product family refers to a group of products produced by the same factory and located in different product hierarchies, such as Huawei mobile phone and Huawei notebook produced by Huawei factory, Huawei mobile phone is located in the mobile phone product hierarchy, Huawei notebook is located in the notebook product hierarchy, Huawei notebook is located in the notebook product hierarchy. A product family for mobile phones and Huawei notebooks

3.2 Code Implementation

3.2.1 Product abstract classes

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public interface ICourse {
    /**
     * Recorded courses
     */
    void record();
}
package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

public interface INote {
    /**
     * Writing Course Notes
     */
    void write();
}
package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

public interface IVideo {
    /**
     * Processing Course Video
     */
    void handle();
}

3.2.2 Specific product categories

package com.zhunongyun.toalibaba.designpatterns.factory.common;

public class JavaCourse implements ICourse {
    /**
     * Recording java courses
     */
    @Override
    public void record() {
        System.out.println("Recording in progress java curriculum");
    }
}
package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

public class JavaNote implements INote {
    @Override
    public void write() {
        System.out.println("Preparing java Course Notes");
    }
}
package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

public class JavaVideo implements IVideo {
    @Override
    public void handle() {
        System.out.println("Processing java Course Video");
    }
}

3.2.3 Factory Interface Class for Creating Objects

package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;

public interface ICourseFactory {
    /**
     * Recorded courses
     * @return
     */
    ICourse createCourse();

    /**
     * Writing Course Notes
     * @return
     */
    INote creatNode();

    /**
     * Processing Course Video
     * @return
     */
    IVideo createVideo();
}

3.2.4 Specific Product Factory Category

package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

import com.zhunongyun.toalibaba.designpatterns.factory.common.ICourse;
import com.zhunongyun.toalibaba.designpatterns.factory.common.JavaCourse;

public class JavaCourseFactory implements ICourseFactory {
    @Override
    public ICourse createCourse() {
        return new JavaCourse();
    }

    @Override
    public INote creatNode() {
        return new JavaNote();
    }

    @Override
    public IVideo createVideo() {
        return new JavaVideo();
    }
}

3.2.5 Test Class

package com.zhunongyun.toalibaba.designpatterns.factory.abstractfactory;

public class AbstractFactoryTest {
    public static void main(String[] args) {
        ICourseFactory courseFactory = new JavaCourseFactory();
        // Recording java courses
        courseFactory.createCourse().record();
        // Writing Notes for java Course
        courseFactory.creatNode().write();
        // Processing java Course Video
        courseFactory.createVideo().handle();
    }
}

3.3 Applicable Scenarios

  • Client (application layer) does not depend on details such as how to create and implement product class instances.
  • Emphasizing that creating objects together with a series of related product objects (which belong to the same product family) requires a lot of repetitive code
  • Provide a library of product classes, all products appear in the same interface, so that the client does not depend on specific implementations.

3.4 Advantages/Disadvantages

3.4.1 Advantages

  • Specific products are segregated at the application level without concern for creating details.
  • Unify a series of product families to create together

3.42 Disadvantages

  • It specifies all possible product aggregates to be created. It is difficult to extend new products in the product family. It is necessary to modify the interface of abstract factories.
  • Increase the abstraction and understanding difficulty of the system

3.5 Source Code Analysis

AbstractBeanFactory class in Spring

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    ......
    
    protected abstract boolean containsBeanDefinition(String var1);

    protected abstract BeanDefinition getBeanDefinition(String var1) throws BeansException;

    protected abstract Object createBean(String var1, RootBeanDefinition var2, @Nullable Object[] var3) throws BeanCreationException;
}

Tags: Java Mobile Apache Spring

Posted on Sat, 24 Aug 2019 06:23:48 -0700 by sushant_d84