[01][01][03] 工厂模式详解

10/18 12:54
阅读数 22

工厂模式分为三种类型

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

1. 简单工厂模式

指由一个工厂对象决定创建出哪一种产品类的实例

1.1 代码实现

1.1.1 产品抽象类

public interface ICourse {
    /**
     * 录制课程
     */
    void record();
}

1.1.2 具体产品类

public class JavaCourse implements ICourse {
    /**
     * 录制 java 课程
     */
    @Override
    public void record() {
        System.out.println("正在录制 java 课程");
    }
}

1.1.3 简单工厂类

public class CourseFactory {

    /**
     * 通过名称创建对象
     * @param name
     * @return
     */
    public ICourse createByName(String name) {
         if ("java".equals(name)) {
             return new JavaCourse();
         } else {
             return null;
         }
    }

    /**
     * 通过类路径创建对象
     * @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;
    }

    /**
     * 通过类创建对象
     * @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 测试类

public class SimelpFactoryTest {

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

        // 通过类名创建对象
        ICourse nameCourse = courseFactory.createByName("java");
        nameCourse.record();

        // 通过类路径创建对象
        ICourse classNameCourse = courseFactory.createByClassPath("com.zhunongyun.toalibaba.designpatterns.factory.common.JavaCourse");
        classNameCourse.record();

        // 通过类创建对象
        ICourse classCourse = courseFactory.createByClass(JavaCourse.class);
        classCourse.record();

        ICourse pythonCourse = courseFactory.createByName("python");
        pythonCourse.record();
    }
}

1.2 适用场景

  • 工厂类负责创建的对象较少
  • 客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心

1.3 优点/缺点

1.3.1 优点

  • 只需要传入一个正确的参数就可以获取你所需要的对象,无需知道其创建细节

1.3.2 缺点

  • 工厂类的职责相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背了开闭原则
  • 不易于扩展过于复杂的产品结构

1.4 源码分析

1.4.1java.util 下的 Calendar

Calendar 是一个日历工具,使用简单工厂模式创建实体类Calendarcalendar=Calendar.getInstance();

Calendar 的 getInstance()的代码就是通过简单工厂的方式去创建 Calendar 对象

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;
    }
}

1.4.2org.slf4j 下的 LoggerFactory

LoggerFactory 是日志工厂类,通过简单工厂创建对象Loggerlogger=LoggerFactory.getLogger("xx");

LoggerFactory 的 getLogger()的代码就是通过简单工厂的方式去创建 Logger 对象

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. 工厂方法模式

指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行

2.1 代码实现

  • 产品抽象类

    public interface ICourse {
    /**
    * 录制课程
    */
    void record();
    }



  • 具体产品类

    public class JavaCourse implements ICourse {
    /**
    * 录制 java 课程
    */
    @Override
    public void record() {
    System.out.println("正在录制 java 课程");
    }
    }






  • 创建对象的工厂接口类

    public interface ICourseFactory {
    /**
    * 创建实体类
    * @return
    */
    ICourse create();
    }




  • 具体产品工厂类

    public class JavaCourseFactory implements ICourseFactory {
    /**
    * 创建 java 课程实体类
    * @return
    */
    @Override
    public ICourse create() {
    return new JavaCourse();
    }
    }







  • 测试类

    public class FactoryMethodTest {
    public static void main(String[] args) {
    ICourseFactory courseFactory = new JavaCourseFactory();
    ICourse course = courseFactory.create();
    course.record();
    }
    }




2.2 适用场景

  • 创建对象需要大量重复的代码
  • 客户端(应用层)不依赖于产品类实例如何被创建,实现等细节
  • 一个类通过其子类来指定创建哪个对象

2.3 优/缺点

2.3.1 优点

  • 用户只需关心所需产品对应的工厂,无需关心创建细节
  • 加入新产品符合开闭原则,提高了系统的可扩展性

2.3.2 缺点

  • 类的个数容易过多,增加了代码结构的复杂度
  • 增加了系统的抽象性和理解难度

2.4 源码分析

2.4.1org.slf4j 下的 LoggerFactory

LoggerFactory 的 getLogger()的代码中ILoggerFactory iLoggerFactory = getILoggerFactory();,通过工厂方法模式创建出具体 Logger 的工厂类

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. 抽象工厂模式

指提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类

3.1 产品等级与产品族

  • 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是手机,其子类有华为手机,小米手机,苹果手机,则抽象手机与具体品牌的手机之间构成了一个产品等级结构,抽象手机是父类,而具体品牌的手机是其子类

  • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如华为工厂生产的华为手机,华为笔记本,华为手机位于手机产品等级结构中,华为笔记本位于笔记本产品等级结构中,华为手机,华为笔记本构成了一个产品族

3.2 代码实现

  • 产品抽象类 java public interface ICourse {
    /**
    * 录制课程
    */
    void record();
    }




public interface INote {
    /**
     * 编写课程笔记
     */
    void write();
}
public interface IVideo {
    /**
     * 处理课程视频
     */
    void handle();
}
  • 具体产品类 java public class JavaCourse implements ICourse {
    /**
    * 录制 java 课程
    */
    @Override
    public void record() {
    System.out.println("正在录制 java 课程");
    }
    }







public class JavaNote implements INote {
    @Override
    public void write() {
        System.out.println("正在编写 java 课程笔记");
    }
}
public class JavaVideo implements IVideo {
    @Override
    public void handle() {
        System.out.println("正在处理 java 课程视频");
    }
}
  • 创建对象的工厂接口类

    public interface ICourseFactory {
    /**
    * 录制课程
    * @return
    */
    ICourse createCourse();
    /**
    * 编写课程笔记
    * @return
    */
    INote creatNode();
    /**
    * 处理课程视频
    * @return
    */
    IVideo createVideo();
    }














  • 具体产品工厂类

    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();
    }
    }











  • 测试类

    public class AbstractFactoryTest {
    public static void main(String[] args) {
    ICourseFactory courseFactory = new JavaCourseFactory();
    // 录制 java 课程
    courseFactory.createCourse().record();
    // 编写 java 课程笔记
    courseFactory.creatNode().write();
    // 处理 java 课程视频
    courseFactory.createVideo().handle();
    }
    }








3.3 适用场景

  • 客户端(应用层)不依赖于产品类实例如何创建,实现等细节
  • 强调一系列相关的产品对象(同属于同一产品族)一起使用创建对象需要大量重复的代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体的实现

3.4 优/缺点

3.4.1 优点

  • 具体产品在应用层代码隔离,无需关心创建细节
  • 将一个系列的产品族统一到一起创建

3.42 缺点

  • 规定了所有可能被创建的产品结集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
  • 增加系统的抽象性和理解难度

3.5 源码分析

Spring 中的 AbstractBeanFactory 类

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;
}

AbstactBeanFactory 的三个实现类:

  • AbstractAutowireCapableBeanFactory
  • XmlBeanFactory
  • DefaultListableBeanFactory

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部