【設計模式】【行爲型模式】模板模式

概念

模板模式定義了一個算法的步驟,並容許子類爲一個或多個步驟提供其實踐方式。讓子類在不改變算法架構的狀況下,從新定義算法中的某些步驟。html

抽象摸板角色:(抽象父類)java

  1. 定義了一個或多個抽象操做,以便讓子類實現
  2. 定義並實現了一個摸板方法

具體摸板角色:(具體實現類)算法

  1. 實現父類所定義的一個或多個抽象方法
  2. 每個抽象摸板角色均可以有任意多個具體摸板角色與之對應
  3. 每個具體摸板角色均可以給出這些抽象方法的不一樣實現

模板方法模式就是基於繼承的代碼複用技術的。在模板方法模式中,咱們能夠將相同部分的代碼放在父類中,而將不一樣的代碼放入不一樣的子類中。也就是說咱們須要聲明一個抽象的父類,將部分邏輯以具體方法以及具體構造函數的形式實現,而後聲明一些抽象方法讓子類來實現剩餘的邏輯,不一樣的子類能夠以不一樣的方式來實現這些邏輯。因此模板方法的模板其實就是一個普通的方法,只不過這個方法是將算法實現的步驟封裝起來的。設計模式

模式中的方法種類:架構

  1. 抽象模板角色裏提供完整的方法,它完成了全部派生類都要用到的一些基本功能。
  2. 抽象模板角色裏只提供空方法,把功能所有留給派生類去實現。
  3. 抽象模板角色裏只包含某些操做的默認實現,派生類裏能夠從新定義這些方法的實現。
  4. 抽象模板角色裏模板方法,他是一個調用抽象方法,鉤子方法以及具體方法的各類組合。

實例

建立一個定義操做的 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);
        }
    }

參考資料:
模板模式
使用模板方法設計模式、策略模式 處理DAO中的增刪改查
設計模式總結

相關文章
相關標籤/搜索