[01][01][03] 工厂模式详解
2020-10-16 21:47
991 查看
工厂模式分为三种类型
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
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
相关文章推荐
- 03_01_Linux文件管理类命令详解
- jsp内置对象【03】request对象详解【01】
- [鸟哥linux视频教程整理]03_01_Linux文件管理类命令详解续3
- java 23种设计模式详解01-02-03-工厂
- 03_01 Linux文件管理类命令详解
- [linux device driver] Chapter 03:以scull_load为引,详解Bash的位置参数和内部参数
- 01_Android应用开发环境_03_开发环境搭建及简单Android程序
- iOS回顾笔记(03) -- 自定义View的封装和xib文件的使用详解
- Wireshark命令行工具tshark详解(含例子)-01
- 背包之01背包、完全背包、多重背包详解
- 【算法学习笔记】14.暴力求解法03 回溯法01 N皇后和素数环
- SpringBoot入门教程03——SpringBoot配置文件详解
- Oracle-->RAC 群集--> Oracle ASM 01 详解
- Java面试03--Overload和Override的区别详解
- 01-03.Java基础windows下搭建环境-安装编程工具 MyEclipse 安装与配置
- 学习笔记(03):Qt图形视图框架详解-Qt图形视图框架详解(上)
- 工厂模式详解(简单工厂+工厂方法+抽象工厂)
- springboot学习之旅03-web开发01
- jsp内置对象【03】request详解【02】
- (原创)c#学习笔记04--流程控制03--分支01--三元运算符