工厂模式-简单工厂模式

工厂模式的好处

1.减少重复代码
2.让创建对象与使用方法分离
3.利于后期维护

简单工厂模式

简单工厂模式(Simple Factory Pattern)是只由一个工厂对象决定创建出哪一种产品类的示例,但他不属于GOF,23种设计模式,简单工厂模式适用于工厂类负责创建的对象比较少的场景。

看如下代码,定义一个ICourse接口:

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

创建它的实现类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");
	}
}

当然,我们为了调用方便,可将 factory 的 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();
}

再看一下类图:
简单工厂模式在 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) {
// 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;
}

还有一个大家经常使用的 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());
}

简单工厂也有它的缺点:工厂类的职责相对过重,不易于扩展过于复杂的产品结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值