Spring Framework 中的9种设计模式
1. 简单工厂模式(Static Factory)
即静态工厂方法(Static Factory Method)模式,但不属于23种GoF设计模式之一。简单工厂模式本质是由一个工厂类根据传入参数,动态决定应该创建哪一个产品类。
Spring中的BeanFactory类即简单工厂模式体现,根据传入的一个唯一标识来获取Bean对象,至于是在传入参数前创建还是在传入参数后创建需具体情况具体分析。
2. 工厂方法模式(Factory Method)
定义一个用于创建对象的接口,由实现子类来决定该实例化哪一个类。工厂方法模式使得一个类的实例化延迟到其子类中实现。
Spring中的FactoryBean即典型的工厂方法模式。如下图:
3. 单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问其的全局访问点。
Spring中的单例模式体现在后半句,提供了全局的访问点BeanFactory,但没有从构造器层面去控制单例,因为Spring管理的是任意的Java对象。
4. 适配器模式(Adapter)
将一个类的接口转换成客户需要的另外一个接口,适配器能够使原本由于接口不兼容而不能一起工作的类可以一起协作。
- Spring中对于AOP的处理有Adapter模式的体现,其中AdvisorAdapter接口的实现子类有AfterReturningAdviceAdapter,MethodBeforeAdviceAdapter,ThrowsAdviceAdapter。
- 由于Advisor链需要MethodInterceptor(拦截器)对象,因此每个Advisor中的Advice都需要适配成对应的MethodInterceptor对象。
5. 装饰器模式(Decorator)
动态的给一个对象添加一些额外的职责。对于增加功能来说,Decorator模式比生成子类更加灵活。
Spring中使用到装饰器模式在类名上有两种体现(都是动态的给一个对象添加一些额外的职责):
- 类名中含有Wrapper。
- 类名中含有Decorator。
如图所示:
6. 代理模式(Proxy)
为其它对象提供一种代理来控制对这个对象的访问。结构上和装饰器模式类似,但Proxy强调的是控制,有点像是对功能的限制,而Decorator更强调增加职责。
Spring中的代理模式主要在Aop中体现,主要是动态代理,有两种代理实现方式:JdkDynamicAopProxy和Cglib2AopProxy。
如下图:
7. 观察者模式(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
Spring中的观察者模式最常见的体现就是Listener的实现,如:ApplicationListener。
如下图:
8. 策略模式(Strategy)
定义一系列算法,并将其全部封装起来,使其之间可相互替换。该模式可以使算法独立于使用它的客户而变化。
Spring在实例化对象的时候使用到策略模式,在InstantiationStrategy接口的实现类SimpleInstantiationStrategy(其中CglibSubclassingInstantiationStrategy为其子类)中说明了策略模式的使用方式:
if(beanDefinition.getMethodOverrides().isEmpty()){
Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;
if(constructorToUse == null){
Class clazz = beanDefinition.getBeanClass();
if(clazz.isInterface()){
throw new BeanInstantiationException(clazz, "Specified clazz is an interface");
}
try{
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse ;
}catch (Exception ex){
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
return BeanUtils.instantiateClass(constructorToUse, null);
}
else{
// must generate CGLIB subclass
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
9. 模板方法(Template Method)
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中去。模板方法使子类不用改变一个算法的结构就可以重定义该算法的某些特定的步骤。
Template Method模式一般需要继承,但还有另一种对模板方法的理解,即Spring中的JdbcTemplate。
在使用JdbcTemplate类时并不想去继承该类,因为这个类的方法太多,但我们还是想用JdbcTemplate已有的稳定的,公用的数据库连接,那该怎么做呢?
解决办法:可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,并且这段代码会使用到JdbcTemplate中的变量,如何做?使用回调对象,在该回调对象中定义一个操纵JdbcTemplate中变量的方法,然后去实现该方法,就把变化的东西集中到这里了,然后再把该回调对象作为参数传入JdbcTemplate,便完成了调用。(这可能是模板方法模式不用继承的一种实现方式)
JdbcTemplate执行execute():
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(this.getDataSource());
Object var4;
try {
Connection conToUse;
if (this.nativeJdbcExtractor != null) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
} else {
conToUse = this.createConnectionProxy(con);
}
var4 = action.doInConnection(conToUse);
} catch (SQLException var8) {
DataSourceUtils.releaseConnection(con, this.getDataSource());
con = null;
throw this.getExceptionTranslator().translate("ConnectionCallback", getSql(action), var8);
} finally {
DataSourceUtils.releaseConnection(con, this.getDataSource());
}
return var4;
}