声明:本篇文章除部分引用外,均为原创内容,如有雷同纯属巧合,引用转载请附上原文链接与声明。*
注:本文若包含部分下载内容,本着一站式阅读的想法,本站提供其对应软件的直接下载方式,但是由于带宽原因下载缓慢是必然的,建立读者去相关官网进行下载,若某些软件禁止三方传播,请在主页上通过联系作者的方式将相关项目进行取消。
参考引用
定义
由工厂对象决定创建出哪一种产品的实例
类型
创建型,但是不属于GOF23种设计模式
适用场景
- 工厂类负责创建的对象比较少
- 客户端(应用层)
优点
只需要传入一个可选择的正确参数,就可以获取到所需要的对象,而无需知道创建的细节
缺点
工厂类的职责相对过重,强依赖于所需要创建的对象类,如果需要该工程能够创建新的工厂,则需要修改工厂类的代码,违背了开闭原则
Coding
需求:某车辆工厂可以根据客户的需求生产各种类型的车辆,比如小轿车,自行车,大卡车。
根据需求,设计出来如下几个类。
车辆基类
public abstract class Vehicle {
/**
* 声明汽车类型
*/
public abstract void printType();
}
小轿车类
public class Car extends Vehicle {
@Override
public void printType() {
System.out.println("小轿车");
}
}
自行车类
public class Bicycle extends Vehicle {
@Override
public void printType() {
System.out.println("自行车");
}
}
大卡车类
public class Truck extends Vehicle {
@Override
public void printType() {
System.out.println("大卡车");
}
}
车辆工厂类
public class VehicleSimpleFactory {
/**
* 根据类型产生指定类型的车辆
* @param type 车辆类型
* @return
*/
public static Vehicle produceVehicle(String type) {
if (type.equals("小轿车")) {
return new Car();
} else if (type.equals("自行车")) {
return new Bicycle();
} else if (type.equals("大卡车")) {
return new Truck();
}
throw new IllegalArgumentException("不支持的汽车类型");
}
}
客户类
public class Client {
/**
* 就直接使用main方法作为客户类的消费方法
* @param args
*/
public static void main(String[] args) {
Vehicle vehicle = VehicleSimpleFactory.produceVehicle("bicycle");
vehicle.printType();
}
}
全局UML
可以从UML中看到,在简单工厂模式中,客户类是不会直接依赖车辆的各个实现类,其所需要的产品类型的创建过程完全又车辆工厂来进行的实现,客户类获取到所需产品后直接使用即可。
JDK源码解析
本次我们解析JDK的java.util.Calendar类,该类是一个抽象类,其UML如下
其中有一个createCalendar()方法,该方法通过入参来决定创建哪个实现类。
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 (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;
}
在switch语法那里可以明显看到其根据入参来判断实例化哪一个实现类,也就是根据需求对所需要的产品进行初始化。除了以上类,还有很多诸如此类使用简单工厂对产品初始化构建过程进行封装,比如JDBC驱动加载等等。