本文节选自《设计模式就该这样学》
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弹架构 』可获取更多技术干货!