工厂方法模式
工厂方法模式是一种实例化对象的模式,属于创建型模式,一般又可以分为简单工厂模式、工厂模式、抽象工厂模式,一般对于需要生成复杂对象的场景中,我们就可以使用工厂方法模式。
实际常用方法
在大多数情况下,我们一般不会像经典实现方式那样去做,而是结合静态方法那样,比如类似下面的这些方法:
看上去是不是也很像是单例模式,没错,实际上可以把两种模式结合一下。
public class InstanceFactory {
private static final Map<String, FruitFactory> FRUIT_FACTORY_MAP = new HashMap<>();
static {
FRUIT_FACTORY_MAP.put("APPLE", new AppleFactory());
FRUIT_FACTORY_MAP.put("BANANA", new BananaFactory());
}
public static Fruit newInstance(String name) {
return FRUIT_FACTORY_MAP.get(name).newInstance();
}
}
public class Test {
public static void main(String[] args) {
Fruit apple = InstanceFactory.newInstance("APPLE");
Fruit banana = InstanceFactory.newInstance("BANANA");
}
}
这样可以减少直接使用工厂模式时存在大量的if else的问题,只不过一般name传的都是class全限定名,然后通过反射的方式获取对象实例。
BeanFactory
Spring中的BeanFactory接口,定义的主要方法就是getBean,顾名思义就是专门用来获取bean对象的方法,那当然也可以看作是一种工厂方法,并且可以通过反射的机制,动态地加载类,从而让所有bean对象只需通过一个BeanFactory工厂就可以完成对象的创建。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
当然除了最常用的getBean方法之外,还有像isSingleton、isPrototype等方法,实际上也是我们在创建对象时需要考虑到的一些因素。
单例、多例
对于工厂方法,我们需要确定创建出来的bean是单例还是多例,Spring框架中,就为我们提供scope属性,用来定义单例或者多例对象。
是否懒加载
就像单例对象的懒汉、饿汉模式一样,对象的加载时机有时候也是需要我们考虑的,因为spring的bean工厂也为我们提供了这个属性的配置。
可以看到,只有非抽象的 && 单例的 && 非懒加载的,才会在spring容器初始化时,通过getBean方法进行bean对象的创建,否则则是等到真正调用时才会创建。
init-method 、 destroy-method
Spring框架优秀之处就在于,提供了各种各样的扩展点,在创建bean对象的时候,你还可以通过init-method方法自定义对象的初始化方法,也可以通过destroy-method方法自定对象的销毁过程。
总结
工厂方法虽然看起来很简单,但是要真正的考虑完善,实际上并没有那么简单,通过了解Spring中的BeanFactory,我们学习到了,首先可以利用反射机制,解决工厂方法中存在大量工厂类的问题,并且在创建bean对象时,还需要考虑对象是单例的还是多例的,是否需要懒加载,以及是否需要支持一些额外的初始化方法。