工厂模式,GoF 的《设计模式》中分为工厂方法和抽象工厂,如果再细一点可以加上简单工厂。
下面看一下源码中的工厂模式的使用。
实例一
JDK 中 java.util.Calendar 类 getInstance 方法使用了简单工厂
public static Calendar getInstance()
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(TimeZone zone)
{
return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
}
public static Calendar getInstance(Locale aLocale)
{
return createCalendar(TimeZone.getDefault(), aLocale);
}
public static Calendar getInstance(TimeZone zone, Locale aLocale)
{
return createCalendar(zone, aLocale);
}
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
...
return cal;
}
实例二
JDK 中反射相关的类也使用了简单工厂
- java.lang.Class 类的 newInstance 方法
@CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
}
- forName 方法
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
- java.lang.reflect.Array 类的 newInstance 方法
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}
- java.lang.reflect.Constructor 类的 newInstance 方法
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
- java.lang.reflect.Proxy 类的 newProxyInstance 方法
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException
{
}
实例三
JDK 中8 种基本类型的包装类 Integer、Long、Short、Character、Byte、Float、Double、Boolean 的 valueOf 方法使用了简单工厂,可以根据参数创建不同的对象。如 Integer 的 valueOf 方法
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
实例四
JDK 中 java.util.Collection 接口的 iterator() 方法运用了抽象工厂模式,Collection 的子接口 List、Set 的子类接口的 iterator() 方法可以创建一系列的迭代器 Iterator
List、Set 的 iterator() 方法就可以理解为运用了工厂方法,子类决定了生成什么样的迭代器 Iterator
实例五
Spring 中 BeanFactory 运用了抽象工厂,它的子类或子接口的 getBean 方法提供了一系列获取 bean 对象的方法
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
}
BeanFactory 的子接口 ConfigurableBeanFactory 接口运用了工厂方法,将 getBean 方法获取对象延迟到 ConfigurableBeanFactory 子类中实现。
AbstractBeanFactory 类的 getBean 方法,可以理解为简单工厂,根据不同参数获取不同的 bean 对象
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
return (T) bean;
}
PS:
- 以上源码部分做了精简
- 工厂方法定义了创建对象的接口,把类的实例化推迟到子类;抽象工厂提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品,本文按照这个理解进行区分。
【Java学习资源】整理推荐
【Java面试题与答案】整理推荐