设计模式——Spring IoC中用到的模板方法模式



基本概念
什么是模板方法(Template method):父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现。
最大的好处:代码复用,减少重复代码。除了子类要实现的特定方法,其他方法及方法调用顺序都在父类中预先写好了。
所以父类模板方法中有两类方法:
1、共同的方法:所有子类都会用到的代码
2、不同的方法:子类要覆盖的方法,分为两种:
A、抽象方法:父类中的是抽象方法,子类必须覆盖
B、钩子方法:父类中是一个空方法,子类继承了默认也是空的
注:为什么叫钩子,子类可以通过这个钩子(方法),控制父类,因为这个钩子实际是父类的方法(空方法)!
模板方法模式,和现实中的模板很像,一个文档的模板通常是一个完成了部分内容的表格(表格模板就像一个模板方法),每个人都会拿到表格的副本(具体的实现类)进行某些项的填写,每个人都可以对指定项(抽象方法或钩子方法)进行填写,表格中的必填项就像抽象方法必须实现,表格中的非必填项就是钩子方法。当然只是比喻和实际情况不完全一样。
UML图

Java代码展示
下面的代码展示了,模板方法模式在Java代码中通常是怎样的:
1、先定义一个接口,主要是定义了模板方法
public interface TemplateInterface {
public void execute();
}
2、抽象类实现了接口,主要是实现了模板方法的逻辑,模板方法中调用了自己的逻辑方法,还有最重要的钩子方法和抽象方法
public abstract class TemplateAbstractClass implements TemplateInterface{
/**模板方法*/
@Override
public void execute() {
preDoSomething();
abstractMethod();
hookMethod();
afterDoSomething();
}
private void preDoSomething(){
System.out.println("before do some thing in abstract class");
}
private void afterDoSomething(){
System.out.println("after do some thing in abstract class");
}
/**抽象方法*/
public abstract void abstractMethod();
/**钩子方法*/
public void hookMethod(){
}
}
3、两个子类,One只实现了抽象方法,Two实现了抽象方法并覆盖了钩子方法
public class SubClassOne extends TemplateAbstractClass{
/**抽象方法*/
@Override
public void abstractMethod() {
System.out.println("do another thing by subClassOne");
}
}
public class SubClassTwo extends TemplateAbstractClass{
/**抽象方法*/
@Override
public void abstractMethod() {
System.out.println("do another thing by subClassTwo");
}
/**钩子方法*/
@Override
public void hookMethod() {
System.out.println("hook method in subClassTwo");
}
}
Spring中的模板方法模式
Spring中几乎所有的扩展,都使用了模板方法模式,JdbcTemplate中应该很多,不过还没学到那里,这里说下IoC部分的模板方法模式!
注:貌似在业务系统中很少看到,是开发者的编码能力问题还是对实际情况不适用,但是在框架中很多,Java IO、Spring、Hibernate等,可能是作为一个框架来说考虑更多的是扩展问题!
下面的代码展示了Spring IOC容器初始化时运用到的模板方法模式。(截取部分关键代码)
1、首先定义一个接口ConfigurableApplicationContext,声明模板方法refresh
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
/**声明了一个模板方法*/
void refresh() throws BeansException, IllegalStateException;
}
2、抽象类AbstractApplicationContext实现了接口,主要实现了模板方法refresh(这个方法很重要,是各种IOC容器初始化的入口)的逻辑
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
/**模板方法的具体实现*/
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.
throw ex;
}
}
}
这里最主要有一个抽象方法obtainFreshBeanFactory、两个钩子方法postProcessBeanFactory和onRefresh,看看他们在类中的定义
两个钩子方法:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
再看看获取Spring容器的抽象方法:
/**其实他内部只调用了两个抽象方法**/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
具体要取那种BeanFactory容器的决定权交给了子类!
3、具体实现的子类,实现了抽象方法getBeanFactory的子类有:
AbstractRefreshableApplicationContext:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
//这里的this.beanFactory在另一个抽象方法refreshBeanFactory的设置的
return this.beanFactory;
}
}
}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
//同样这里的this.beanFactory在另一个抽象方法中设置
return this.beanFactory;
}
}
其实这里的差别还不是很大,我们可以看看另一个抽象方法refreshBeanFactory的实现,两个抽象方法的配合使用。
所以这里的UML是:



设计模式——Spring IoC中用到的模板方法模式的更多相关文章
- Android设计模式(八)--模板方法模式
到国美面试Android的时候.问我的设计模式相关的问题: 1.单例模式的意义时什么. 2.有哪几种工厂方法模式: 3.你用过的模板方法模式.举例说明: 自己感觉答的一塌糊涂. 模板方法模式都没说出来 ...
- 设计模式(二十二)模板方法模式 Template
泡茶?泡咖啡? 我们用泡茶和泡咖啡两种行为来引入这一设计模式. 思考一下“泡茶”的过程: 煮水 -> 用沸水泡茶叶 -> 把茶倒进杯子 -> 放点柠檬之类的佐料. 然后再看一下“泡咖 ...
- 折腾Java设计模式之模板方法模式
博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...
- 应聘阿里,字节跳动,美团必须掌握的Spring IOC与工厂模式
Spring IOC与工厂模式 PS:本文内容较为硬核,需要对java的面向对象.反射.类加载器.泛型.properties.XML等基础知识有较深理解. (一)简单介绍 在讲Spring IOC之前 ...
- 设计模式 - 模板方法模式详解及其在Spring中的应用
基本介绍 模板方法模式(Template Method Pattern)也叫模板模式,它在一个抽象类中公开定义了执行它的方法的模板,它的字类可以按需重写方法实现,但调用将以抽象类中定义的方式进行. 简 ...
- 设计模式 : Template method 模板方法模式 -- 行为型
设计模式中,模板模式面向的是方法级别的流程.(不过好像世界上大部分问题,都可以抽象点.抽象点吧,最后抽象到一个方法里面吧.) 1. 一个方法,可以用来描述一个流程,这个流程涉及多个环节,不同环节可 ...
- [.net 面向对象程序设计深入](26)实战设计模式——使用Ioc模式(控制反转或依赖注入)实现松散耦合设计(1)
[.net 面向对象程序设计深入](26)实战设计模式——使用IoC模式(控制反转或依赖注入)实现松散耦合设计(1) 1,关于IOC模式 先看一些名词含义: IOC: Inversion of con ...
- javascript设计模式——模板方法模式
前面的话 在javascript开发中用到继承的场景其实并不是很多,很多时候喜欢用mix-in的方式给对象扩展属性.但这不代表继承在javascript里没有用武之地,虽然没有真正的类和继承机制,但可 ...
- [.net 面向对象程序设计深入](31)实战设计模式——使用Ioc模式(控制反转或依赖注入)实现松散耦合设计(1)
[.net 面向对象程序设计深入](31)实战设计模式——使用IoC模式(控制反转或依赖注入)实现松散耦合设计(1) 1,关于IOC模式 先看一些名词含义: IOC: Inversion of con ...
随机推荐
- 深入理解PHP内核(九)变量及数据类型-静态变量
原文链接:http://www.orlion.ga/251/ 通常静态变量是静态分配的,他们的生命周期和程序的生命周期一样长,只有在程序退出后才结束生命周期,这和局部变量相反,有的语言中全局变量也是静 ...
- java中finally和return的执行顺序
注意:return的位置... 从这几个例子中可以看到,如果try之前没有有条件的return,则try..catch..finally语句块中的语句都是顺序执行(如果try中或者catch中 有re ...
- MySQL的学习--触发器
MySQL包含对触发器的支持.触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行. 创建触发器 在MySQL中,创建触发器语法如下 ...
- Linux的学习--crontab
之前了解过一点crontab,前段时间比较闲,就熟悉了一下,今天总结记录一下. crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并 ...
- [OpenCV] Samples 06: [ML] logistic regression
logistic regression,这个算法只能解决简单的线性二分类,在众多的机器学习分类算法中并不出众,但它能被改进为多分类,并换了另外一个名字softmax, 这可是深度学习中响当当的分类算法 ...
- [c++] Pieces of knowledge
再系统地学一遍c++,查缺补漏. wchar_t L'a' stored in wchar_t. size of types cout << numeric_limits<doubl ...
- Sybase数据库收集表及其索引的统计信息
更新表及其索引的统计信息: update table statistics 表名 go update index statistics 表名 go 建议此操作在闲时操作.
- github代码管理工具的使用方法
一.创建一个存储库 1.点击页面右上方你的用户名右边的+标志,然后点击下拉列表中的"new repository"选项,一般填写项目名称和选择public 和选择初始化有READM ...
- app令牌的一个token实现
app登陆验证不能使用session来判断了.然后查资料都说用令牌,没找到合适的方法,我的眼界太小.另外,越来越感觉基础的重要,比如,session是什么,我竟无言以对.不知道session是什么,怎 ...
- JAVA 设计模式 组合模式
用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模式. 结构