工厂模式在开源代码中的应用
工厂模式,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 方法
@CallerSensitivepublic T newInstance() throws InstantiationException, IllegalAccessException{}
forName 方法
@CallerSensitivepublic 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 方法
@CallerSensitivepublic 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 方法
@CallerSensitivepublic 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:
以上源码部分做了精简
工厂方法定义了创建对象的接口,把类的实例化推迟到子类;抽象工厂提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品,本文按照这个理解进行区分。
更多相关文章
- 构造方法的参数太多,如何解决?
- 面试官:为什么静态方法不能调用非静态方法和变量?
- ConcurrentHashMap之size()方法
- 为什么不推荐使用finalize方法,来看看对垃圾回收有什么影响吧
- java8中的一个骚操作-方法引用(使代码看起来很高大上)