【源码分析设计模式 9】SpringIOC 中的模板方法模式
============
1、优点
(1)模板方法模式通过把不变的行为搬移到父类,去除了子类中的重复代码。
(2)子类实现算法的某些细节,有助于算法的扩展。
(3)通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2、缺点
按照设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类负责完成具体的事务属性和方法,但是模板方式正好相反,子类执行的结果影响了父类的结果,会增加代码阅读的难度。
四、模板方法模式的使用场景
=============
1、多个子类有共有的方法,并且逻辑基本相同。
2、重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
3、重构时,模板方法是一个经常使用的方法,把相同的代码抽取到父类中,然后通过构造函数约束其行为。
五、钩子方法
======
1、在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况覆盖它,该方法称为钩子方法。
六、代码实例
======
1、抽象类
package com.guor.template;
public abstract class SoyaMilk {
//模板方法, make , 模板方法可以做成 final , 不让子类去覆盖.
final void make() {
select();
addCondiments();
soak();
beat();
}
//选材料
void select() {
System.out.println("第一步:选择好的新鲜黄豆 ");
}
//添加不同的配料, 抽象方法, 子类具体实现
abstract void addCondiments();
//浸泡
void soak() {
System.out.println("第三步, 黄豆和配料开始浸泡, 需要 3 小时 ");
}
void beat() {
System.out.prin
tln("第四步:黄豆和配料放到豆浆机去打碎 ");
}
}
2、花生类
package com.guor.template;
public class PeanutSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println(" 加入上好的花生 ");
}
}
3、红豆类?
package com.guor.template;
public class RedBeanSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
System.out.println(" 加入上好的红豆 ");
}
public static void main(String[] args) {
//制作红豆豆浆
System.out.println("----制作红豆豆浆----");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("----制作花生豆浆----");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}
4、控制台输出
七、SpringIOC 中的模板方法模式
Spring 中几乎所有的扩展都是用了模板方法模式,以 SpringIOC 为例简单说明一下。
1、首先定义一个接口 ConfigurableApplicationContext,声明模板方法 refresh。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
/*声明了一个模板方法/
void refresh() throws BeansException, IllegalStateException;
}
2、抽象类 AbstractApplicationContext 实现了接口
主要实现了模板方法 refresh(这个方法很重要,是各种 IOC 容器初始化的入口)的逻辑。
/**
模板方法的具体实现
*/
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
//注意这个方法是,里面调用了两个抽象方法 refreshBeanFactory、getBeanFactory
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//注意这个方法是钩子方法
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
//注意这个方法是钩子方法
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
评论