模板模式定义了一个算法的步骤,并容许子类为一个或多个步骤提供其实践方式。让子类在不改变算法架构的状况下,从新定义算法中的某些步骤。html
抽象摸板角色:(抽象父类)java
- 定义了一个或多个抽象操做,以便让子类实现
- 定义并实现了一个摸板方法
具体摸板角色:(具体实现类)算法
- 实现父类所定义的一个或多个抽象方法
- 每个抽象摸板角色均可以有任意多个具体摸板角色与之对应
- 每个具体摸板角色均可以给出这些抽象方法的不一样实现
模板方法模式就是基于继承的代码复用技术的。在模板方法模式中,咱们能够将相同部分的代码放在父类中,而将不一样的代码放入不一样的子类中。也就是说咱们须要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数的形式实现,而后声明一些抽象方法让子类来实现剩余的逻辑,不一样的子类能够以不一样的方式来实现这些逻辑。因此模板方法的模板其实就是一个普通的方法,只不过这个方法是将算法实现的步骤封装起来的。设计模式
模式中的方法种类:架构
建立一个定义操做的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。Cricket 和 Football 是扩展了 Game 的实体类,它们重写了抽象类的方法。app
TemplatePatternDemo,咱们的演示类使用 Game 来演示模板模式的用法。ide
步骤 1函数
建立一个抽象类,它的模板方法被设置为 final。post
Game.java public abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); //模板 public final void play(){ //初始化游戏 initialize(); //开始游戏 startPlay(); //结束游戏 endPlay(); } }
步骤 2
建立扩展了上述类的实体类。this
Cricket.java public class Cricket extends Game { @Override void endPlay() { System.out.println("Cricket Game Finished!"); } @Override void initialize() { System.out.println("Cricket Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Cricket Game Started. Enjoy the game!"); } } Football.java public class Football extends Game { @Override void endPlay() { System.out.println("Football Game Finished!"); } @Override void initialize() { System.out.println("Football Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } }
步骤 3
使用 Game 的模板方法 play() 来演示游戏的定义方式。
TemplatePatternDemo.java public class TemplatePatternDemo { public static void main(String[] args) { Game game = new Cricket(); game.play(); System.out.println(); game = new Football(); game.play(); } }
步骤 4
验证输出。
Cricket Game Initialized! Start playing. Cricket Game Started. Enjoy the game! Cricket Game Finished! Football Game Initialized! Start playing. Football Game Started. Enjoy the game! Football Game Finished!
在Spring中的AbstractApplicationContext的refresh方法中使用了模板模式。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // 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. beanFactory.destroySingletons(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
AbstractApplicationContext类中的refresh定义好了代码逻辑骨架,obtainFreshBeanFactory()方法中调用了refreshBeanFactory();
,该方法在AbstractApplicationContext中是抽象方法,须要在子类中具体实现。
//AbstractApplicationContext protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isInfoEnabled()) { logger.info("Bean factory for application context [" + getId() + "]: " + ObjectUtils.identityToString(beanFactory)); } if (logger.isDebugEnabled()) { logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this); } return beanFactory; } protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
查看AbstractApplicationContext的子类
最终类是FileSystemXmlApplicationContext,方法的具体实如今AbstractRefreshableApplicationContext中能够找到。
//AbstractRefreshableApplicationContext protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException( "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex); } }