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

43次阅读

共计 3377 个字符,预计需要花费 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 弹架构』可获取更多技术干货!

正文完
 0