[01][01][03] 工厂模式详解
作者:互联网
工厂模式分为三种类型
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
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
标签:03,01,return,ICourse,class,详解,new,工厂,public 来源: https://blog.51cto.com/14962454/2542173