模板模式定義了一個算法的步驟,並容許子類爲一個或多個步驟提供其實踐方式。讓子類在不改變算法架構的狀況下,從新定義算法中的某些步驟。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); } }