写点什么

彻底说透简单工厂那些你没有关注过的细节

作者:Tom弹架构
  • 2021 年 11 月 10 日
  • 本文字数:2595 字

    阅读完需:约 9 分钟

本文节选自《设计模式就该这样学》

1 使用简单工厂模式封装产品创建细节

接下来看代码,还是以创建一门网络课程为例。假设有 Java 架构、大数据、人工智能等课程,已经形成了一个生态。我们可以定义一个课程标准 ICourse 接口。



public interface ICourse { /** 录制视频 */ public void record();}
复制代码


创建一个 Java 课程的实现类 JavaCourse。



public class JavaCourse implements ICourse { public void record() { System.out.println("录制Java课程"); }}
复制代码


客户端调用代码如下。



public static void main(String[] args) { ICourse course = new JavaCourse(); course.record();}
复制代码


由上面代码可知,父类 ICourse 指向子类 JavaCourse 的引用,应用层代码需要依赖 JavaCourse。如果业务扩展,则继续增加 PythonCourse,甚至更多,那么客户端的依赖会变得越来越臃肿。因此,我们要想办法把这种依赖减弱,把创建细节隐藏。虽然在目前的代码中,创建对象的过程并不复杂,但从代码设计角度来讲不易于扩展。因此,用简单工厂模式对代码进行优化。首先增加课程 PythonCourse 类。



public class PythonCourse implements ICourse { public void record() { System.out.println("录制Python课程"); }}
复制代码


然后创建 CourseFactory 工厂类。



public class CourseFactory { public ICourse create(String name){ if("java".equals(name)){ return new JavaCourse(); }else if("python".equals(name)){ return new PythonCourse(); }else { return null; } }}
复制代码


最后修改客户端调用代码。



public class SimpleFactoryTest { public static void main(String[] args) { CourseFactory factory = new CourseFactory(); factory.create("java"); }}
复制代码


当然,为了调用方便,可将 CourseFactory 的 create()方法改为静态方法,其类图如下图所示。



客户端调用虽然简单了,但如果业务继续扩展,要增加前端课程,则工厂中的 create()方法就要随着产品链的丰富每次都要修改代码逻辑,这不符合开闭原则。因此,我们可以采用反射技术继续对简单工厂模式进行优化,代码如下。



public class CourseFactory { public ICourse create(String className){ try { if (!(null == className || "".equals(className))) { return (ICourse) Class.forName(className).newInstance(); } }catch (Exception e){ e.printStackTrace(); } return null; }}
复制代码


客户端调用代码修改如下。



public static void main(String[] args) { CourseFactory factory = new CourseFactory(); ICourse course = factory.create("com.gupaoedu.vip.pattern.factory.simplefactory.JavaCourse"); course.record();}
复制代码


优化之后,产品不断丰富,不需要修改 CourseFactory 中的代码。但问题是,方法参数是字符串,可控性有待提升,而且还需要强制转型。继续修改代码。



public ICourse create(Class<? extends ICourse> clazz){ try { if (null != clazz) { return clazz.newInstance(); } }catch (Exception e){ e.printStackTrace(); } return null;}
复制代码


优化客户端测试代码。



public static void main(String[] args) { CourseFactory factory = new CourseFactory(); ICourse course = factory.create(JavaCourse.class); course.record();}
复制代码


最后来看如下图所示的类图。


2 简单工厂模式在 JDK 源码中的应用

简单工厂模式在 JDK 源码中无处不在,例如 Calendar 类,看 Calendar.getInstance()方法。下面打开的是 Calendar 的具体创建类。



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) { } }
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 (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;}
复制代码

3 简单工厂模式在 Logback 源码中的应用

在大家经常使用的 Logback 中,可以看到 LoggerFactory 中有多个重载的方法 getLogger()。



public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name);}
public static Logger getLogger(Class clazz) { return getLogger(clazz.getName());}
复制代码


【推荐】Tom弹架构:收藏本文,相当于收藏一本“设计模式”的书


本文为“Tom 弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!

如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。关注微信公众号『 Tom 弹架构 』可获取更多技术干货!

发布于: 9 小时前阅读数: 13
用户头像

Tom弹架构

关注

不只做一个技术者,更要做一个思考者 2021.10.22 加入

畅销书作者,代表作品: 《Spring 5核心原理与30个类手写实战》 《Netty 4核心原理与手写RPC框架实战》 《设计模式就该这样学》

评论

发布
暂无评论
彻底说透简单工厂那些你没有关注过的细节