本章内容概要:
一.概念
根据不同的参数返回不同的类的实例
注:简单工厂模式不在GOF四人组所列的23种设计模式之中
二.角色
1.工厂 : 负责创建不同的类的实例
2.抽象产品(接口) : 所有产品类的父类,负责描述产品的公共接口
3.具体产品 : 具体的产品的目标
三.优缺点
1.优点
- 客户端无须知道创建具体的产品类名,只需知道具体产品对象的参数即可
- 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类
2.缺点
- 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,可能影响所有产品类
- 增加新产品时,需要修改工厂类
四.适用场景
- 创建的对象对象比较少的情况
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心
五.实例
1.抽象产品
/**
* 电脑(接口)
* @author shixinke
*/
public interface Computer {
/**
* 获取电脑的名称(型号)
* @return
*/
String getName();
/**
* 获取操作系统名称
* @return
*/
String getOsName();
}
2.具体的产品
(1)具体产品1
/**
* 戴尔电脑
* @author shixinke
*/
public class DellComputer implements Computer {
public String getName() {
return "戴尔(DELL)";
}
public String getOsName() {
return "Windows 7";
}
}
(2)具体产品2
/**
* mac电脑
* @author shixinke
*/
public class MacComputer implements Computer {
public String getName() {
return "Mac 2018";
}
public String getOsName() {
return "Mac OS";
}
}
(3)具体产品3
/**
* thinkPad电脑
* @author shixinke
*/
public class ThinkPadComputer implements Computer {
public String getName() {
return "ThinkPad";
}
public String getOsName() {
return "Windows 10";
}
}
3.工厂类
/**
* 电脑工厂
*/
public class ComputerFactory {
/**
* 生产电脑的方法
* @param name
* @return
*/
public static Computer getComputer(String name) {
if ("Dell".equalsIgnoreCase(name)) {
return new DellComputer();
} else if ("Mac".equalsIgnoreCase(name)) {
return new MacComputer();
} else if ("ThinkPad".equalsIgnoreCase(name)) {
return new ThinkPadComputer();
}
return null;
}
}
4.调用端
/**
* 电脑测试类
* @author shixinke
*/
public class ComputerTest {
public static void main(String[] args) {
Computer c1 = ComputerFactory.getComputer("thinkpad");
System.out.println("name = " + c1.getName() + "; os = " + c1.getOsName());
Computer c2 = ComputerFactory.getComputer("mac");
System.out.println("name = " + c2.getName() + "; os = " + c2.getOsName());
Computer c3 = ComputerFactory.getComputer("dell");
System.out.println("name = " + c3.getName() + "; os = " + c3.getOsName());
}
}
以上类的UML关系图:
六.源码实例
1.JDK中使用的简单式工厂模式
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) {
/**
* 通过caltype来确认实例化哪个具体的类
*/
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;
}
注:
- Calendar :可认为是一个抽象产品
- createCalendar : 简单工厂
- JapaneseImperialCalendar和GregorianCalenda为具体的产品