简单工厂是由一个工厂对象来决定创建出哪一种产品类的实例。属于创建型,但不属于GOF23种设计模式,更像是一种编码的风格和习惯。
学习简单工厂后,对于学习工厂方法、抽象工厂更有帮助。
适用范围
- 1.工厂类负责创建的对象比较少。
- 2.客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。
优缺点
优点:只需要传入一个正确的参数,就可以获取你所需要的对象,无需知道其创建细节。
缺点:工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则。
示例
Video.java
视频抽象类,提供生产视频的抽象方法。
package com.zaiae.design.pattern.creational.simplefactory;
public abstract class Video {
public abstract void produce();
}
JavaVideo.java
Java视频类,继承视频抽象类,并实现自己的生产视频逻辑。
package com.zaiae.design.pattern.creational.simplefactory;
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制一套Java课程视频");
}
}
PythonVideo.java
Python视频类,继承视频抽象类,并实现自己的生产视频逻辑。
package com.zaiae.design.pattern.creational.simplefactory;
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制一套Python课程视频");
}
}
VideoFactory.java
生产视频的简单工厂类,通过传入参数,生产不同的视频对象。
package com.zaiae.design.pattern.creational.simplefactory;
public class VideoFactory {
public Video getVideo(String type) {
switch (type.toLowerCase()) {
case "java":
return new JavaVideo();
case "python":
return new PythonVideo();
default:
return null;
}
}
}
Test.java
客户端(应用层)调用简单工厂,创建需要的对象。
package com.zaiae.design.pattern.creational.simplefactory;
public class Test {
public static void main(String[] args) {
VideoFactory videoFactory = new VideoFactory();
Video video = videoFactory.getVideo("python");
if (video != null) {
video.produce();
}
}
}
UML结构图:

JDK中的使用例子
在jdk源码中,也大量使用了简单工厂,比如 java.util.Calendar
类中,创建 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;
}
换友链啦 https://www.finen.top
谢谢分享