设计模式——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 ...
随机推荐
- ASP.NET MVC中简单使用Autofac
项目中引入Autofac的目的是为了实现控制反转,即IoC,Inversion of Control.控制反转可以有效的降低类之间的相互依赖关系,增加架构的弹性,降低软件复杂度. 示例代码: IPro ...
- mysql load data infile的使用 和 SELECT into outfile备份数据库数据
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE t ...
- Yii2的深入学习--继承关系
想要了解 Yii2 的话,一定要对 Yii2 中相关类的继承关系有所了解.由于暂时读的代码有限,下面的图中只列出了部分继承关系,之后回跟着源码阅读的越来越多而增加 由上图可以看到 Yii2 中大多数类 ...
- 麒麟系统使用root权限运行程序
最近在虚拟机里安装了个国产麒麟系统.(不知道麒麟系统的百度下.) ************************************************** 官方网址:http://www. ...
- Windows Azure HandBook (9) Azure性能测试(2)
<Windows Azure Platform 系列文章目录> 在上一节中,笔者介绍了我们在Azure性能测试之前,首先需要提交<渗透性测试表> Windows Azure H ...
- swift分号的使用
与其他大部分编程语言不同,Swift 并不强制要求你在每条语句的结尾处使用分号(;),当然,你也可以按照你自己的习惯添加分号.有一种情况下必须要用分号,即你打算在同一行内写多条独立的语句 let yo ...
- 模拟 --- hdu 12878 : Fun With Fractions
Fun With Fractions Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB Total submit ...
- C语言学习006:歌曲搜索
#include <stdio.h> #include <string.h> //字符串处理库 ]={ "I left my heart in Harvard Med ...
- Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用
前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...
- 利用JavaScript函数对字符串进行加密
加密.解密问题对我来说一直是很神秘的,感到神奇无比. 理论了解 前段时间看到关于利用JavaScript函数unescape()和escape()对字符串进行替换处理.通过查资料得知, escape( ...