设计模式——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 ...
随机推荐
- 开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀
1.前言 随着云IM的发展,已吸引越来越多有IM需求的APP接入.但考虑到云IM无论从商业模式还是运营模式上,还需经过多年的沉淀,才可能真正实现客户与服务商的运营和服务良性循环的双赢局面.在此之前,加 ...
- python中paramiko模块的使用
paramiko是python一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接1.可以远程操作服务器文件 例如: df:查看磁盘使用情况 mkdir:创建目录 mv/cp/mk ...
- Wait Type:IO_COMPLETION
在等待 CXPACKET 完成的时间内,我查看 sys.dm_exec_requests ,发现Session的 Logical Read/Write, Physical Read 都没有变化.Wai ...
- 怎样将多个CSS文件导入一个CSS文件中
问题: 在HTML中引入css的其中的两个方法: 导入式和链接式的目的都是将一个独立的css文件引入一个文件中,二者的区别不大,事实上,二者最大的区别在于链接式使用html的标记引入外部css文 ...
- Package gp in the OpenCASCADE
Package gp in the OpenCASCADE eryar@163.com China 一.简介 Introduction to Package gp gp是几何处理程序包(Geometr ...
- javascript基础语法——变量和标识符
× 目录 [1]定义 [2]命名规则 [3]声明[4]特性[5]作用域[6]声明提升[7]属性变量 前面的话 关于javascript,第一个比较重要的概念是变量,变量的工作机制是javascript ...
- c++中关于初始化型参列表的一些问题
/* 1.成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的! 一个好的习惯是,按照成员定义的顺序进行初始化. 2.数组成员在初始化型参列表中不正确 */ #in ...
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
概要 本章是"JUC系列"的CopyOnWriteArrayList篇.接下来,会先对CopyOnWriteArrayList进行基本介绍,然后再说明它的原理,接着通过代码去分析, ...
- Spring MVC 学习总结(六)——Spring+Spring MVC+MyBatis框架集成
与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC负责请求的转发和 ...
- Dapper的基本使用
Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的.也就是说实体类都要自己写.它没有复杂的配置文件,一个单文件就可 ...