您的位置:首页 > 其它

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

start_new 2020-10-16 21:47 106 查看 https://blog.51cto.com/1496245
  • 1.2 适用场景
  • 1.3 优点/缺点
  • 1.4 源码分析
  • 2. 工厂方法模式
  • 2.4 源码分析
  • 3. 抽象工厂模式
  • 3.5 源码分析
  • 工厂模式分为三种类型

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

    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 优点

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

    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

    标签: