写点什么

【源码分析设计模式 9】SpringIOC 中的模板方法模式

  • 2021 年 11 月 11 日
  • 本文字数:1982 字

    阅读完需:约 7 分钟

============


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


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


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.

评论

发布
暂无评论
【源码分析设计模式 9】SpringIOC中的模板方法模式