模板方法设计模式

模板方法设计模式


1. 简单介绍

模板方法设计模式是一种结构型设计模式。该模式定义了一个算法的骨架(方法执行的步骤),将算法的各个步骤的具体实现,交由子类完成。模板方法设计模式,让开发者只需要关注算法实现各个细节,而不必关系算法实现的全部流程。

2. 使用场景
  • 具有统一的算法骨架,即方法执行步骤是固定不变的
  • 针对不同的场景,存在多个具有相同操作步骤的应用场景,但部分算法的实现细节有所差异
3. 场景举例

Spring中的事务管理的设计采用了模板方法设计模式。事务的使用步骤可以抽象为:开启事务、相关操作、提交事务。针对上述步骤中的“开启事务”和“提交事务”,可由模板方法进行固定。而具体的“相关操作”,针对不同的子类可以有不同的实现。

4. UML类图

模板方法模式UML类图

5. 具体实现

描述

  • 背景:活字印刷术,可以根据自己的需求,组合不同的汉字,将组合后的汉字按顺序印刷出自己想要的词组或句子,现假设现有一块印刷版支持三个字的组合,任意组合
  • AbstractPrintBoardAbstractClass角色,表示印刷版,用于用户自由组合三个汉字进行印刷
  • PrintBoardOneConcreteClass角色,可对“你”、“真”、“好”三个汉字进行组合印刷
  • PrintBoardTwoConcreteClass角色,可对“你”、“真”、“坏”三个汉字进行组合印刷

实现代码

AbstractPrintBoard.java

/**
 * 角色:AbstractClass
 * 印刷版,用于用户自由组合三个汉字进行印刷
 */  
public abstract class AbstractPrintBoard {

    /**
     * 模版方法:控制汉字印刷顺序
     * 先印刷 chineseCharacter1、再印刷 chineseCharacter2,最后印刷 chineseCharacter3
     */
    public void print() {
     System.out.println(String.format("%c%c%c", chineseCharacter1(), chineseCharacter2(), chineseCharacter3()));
    }

    /**
     * 交由具体子类进行实现(具体哪几个汉字进行组合)
     */
    public abstract char chineseCharacter1();

    public abstract char chineseCharacter2();

    public abstract char chineseCharacter3();

}

PrintBoardOne.java

/**
    * 角色:具体实现子类
    * 组合“你”、“真”、“好”三个汉字进行印刷
    */
   public class PrintBoardOne extends AbstractPrintBoard {
   
           @Override
           public char chineseCharacter1() {
               return '你';
           }

           @Override
           public char chineseCharacter2() {
               return '真';
           }

           @Override
           public char chineseCharacter3() {
               return '好';
           }
    }

PrintBoardTwo.java

/**
 * 角色:具体实现子类
 * 组合“你”、“真”、“坏”三个汉字进行印刷
 */
public class PrintBoardTwo extends AbstractPrintBoard {

    @Override
    public char chineseCharacter1() {
        return '你';
    }

    @Override
    public char chineseCharacter2() {
        return '真';
    }

    @Override
    public char chineseCharacter3() {
        return '坏';
    }
}

Client.java

/**
 * 模版方法模式具体使用
 */
public class Client {

    public static void main(String[] args) {
        // AbstractPrintBoard控制了印刷汉字的顺序,具体印刷哪几个汉字,加油子类进行实现
        // 印刷“你真好”三个汉字,输出:你真好
        AbstractPrintBoard board1 = new PrintBoardOne();
        board1.print();

        // 印刷“你真坏”三个汉字,输出:你真坏
        AbstractPrintBoard board2 = new PrintBoardTwo();
        board2.print();
    }
}
7. 源码展示

Spring源码中的ApplicationContex的部分功能的实现实现采用了模板方法设计模式。其中模板方法模式中抽象类角色对应AbstractApplicationContext,该类中定义了refresh()方法的流程步骤,即模板方法。具体子类角色对应的类为GenericApplicationContext,并实现了抽象方法refreshBeanFactory()

AbstractApplicationContext.java

/**
 * 角色:模板方法中的抽象类
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    
    /**
     * refresh()相当于模版方法模式中的模板方法,确保了刷新的具体步骤
     * 部分具体的刷新步骤交给其子类进行具体的实现
     */
    @Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// obtainFreshBeanFactory()方法调用了抽象方法refreshBeanFactory();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
                // 抽象方法,交由子类实现
				postProcessBeanFactory(beanFactory);
			} catch (BeansException ex) {
                ......
			} finally {
				......
			}
		}
	} 
    
    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;
    
    /**
     * 默认是空实现的抽象方法,也称为钩子方法
     * 子类可按需求,选择是否进行重写
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}
}

GenericApplicationContext.java

/**
 * 角色:模板方法中的具体子类
 */
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { 
    
    /**
     * 抽象方法的具体实现
     */
    @Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值