【设计模式】【行为型模式】模板模式

概念

模板模式定义了一个算法的步骤,并容许子类为一个或多个步骤提供其实践方式。让子类在不改变算法架构的状况下,从新定义算法中的某些步骤。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中的增删改查
设计模式总结

相关文章
相关标签/搜索