定义
模板方法是一种行为设计模式,它定义了一个算法的骨架,将某些步骤的具体实现推迟到子类中。这种模式允许在不改变算法整体结构的情况下,通过子类重写方法来修改算法的某些步骤。
意图
定义算法骨架: 定义一个算法的主要结构,将具体步骤的实现延迟到子类中。
允许扩展特定步骤: 允许子类根据需要重写或扩展父类中的特定步骤,同时保持整体算法结构不变。
参与者(角色)
- 抽象类(Abstract Class):定义算法的抽象骨架,包含算法中的各个步骤的框架和顺序,但留下某些步骤的实现细节由子类实现。定义了模板方法,作为算法骨架的整体结构。
- 具体类(Concrete Class):实现抽象类中的抽象方法,完成具体的算法细节。实现父类中定义的模板方法,覆盖或扩展算法中的特定步骤。
举例
已创建订单为例
类图:

这个例子中对应类的角色如下:
OrderProcessing类
public abstract class OrderProcessing {
public void processOrder(String productName,int amount){
boolean flag= validateOrder(productName,amount);
if(flag){
Order order= createOrder(productName,amount);
dispatchOrder(order);
compleateOrder(order);
}
}
protected abstract void compleateOrder(Order order);
protected abstract void dispatchOrder(Order order);
protected abstract Order createOrder(String productName ,int amount) ;
protected abstract boolean validateOrder(String productName,int amount) ;
}
OnlineShoppingOrder类
@Slf4j
public class OnlineShoppingOrder extends OrderProcessing{
@Override
protected void compleateOrder(Order order) {
log.info("网购订单:{} 已完成!",order.getOrderId());
}
@Override
protected void dispatchOrder(Order order) {
log.info("网购订单:{} 运输中",order.getOrderId());
}
@Override
protected Order createOrder(String productName ,int amount) {
Order order = new Order();
order.setOrderId(RandomUtils.nextLong()+"");
order.setProcudtName(productName);
order.setProductAmount(amount);
log.info("网购订单创建完成:{}",order.getOrderId());
return order;
}
@Override
protected boolean validateOrder(String productName ,int amount) {
OrderService orderService = new OrderService();
int stock = orderService.getAmount(productName);
if(stock>=amount){
return true;
}
log.error("产品名称:{},库存不足,剩余:{}",productName,stock);
return false;
}
}
EcommerceOrder支付类
@Slf4j
public class EcommerceOrder extends OrderProcessing{
@Override
protected void compleateOrder(Order order) {
log.info("电子商务订单:{} 已完成!",order.getOrderId());
}
@Override
protected void dispatchOrder(Order order) {
log.info("电子商务订单: {} 运输中!",order.getOrderId());
}
@Override
protected Order createOrder(String productName ,int amount) {
Order order = new Order();
order.setOrderId(RandomUtils.nextLong()+"");
order.setProcudtName(productName);
order.setProductAmount(amount);
log.info("电子商务订单创建完成:{}",order.getOrderId());
return order;
}
@Override
protected boolean validateOrder(String productName ,int amount) {
OrderService orderService = new OrderService();
int stock = orderService.getAmount(productName);
if(stock>=amount){
return true;
}
log.error("产品名称:{},库存不足,剩余:{}",productName,stock);
return false;
}
}
RestaurantOrder类
@Slf4j
public class RestaurantOrder extends OrderProcessing{
@Override
protected void compleateOrder(Order order) {
log.info("超市订单:{} 已完成!",order.getOrderId());
}
@Override
protected void dispatchOrder(Order order) {
log.info("超市订单:{} 运输中!",order.getOrderId());
}
@Override
protected Order createOrder(String productName ,int amount) {
Order order = new Order();
order.setOrderId(RandomUtils.nextLong()+"");
order.setProcudtName(productName);
order.setProductAmount(amount);
log.info("超市订单创建完成:{}",order.getOrderId());
return order;
}
@Override
protected boolean validateOrder(String productName ,int amount) {
OrderService orderService = new OrderService();
int stock = orderService.getAmount(productName);
if(stock>=amount){
return true;
}
log.error("产品名称:{},库存不足,剩余:{}",productName,stock);
return false;
}
}
OrderService支付类
@Service
public class OrderService {
static Map<String,Integer> products = new HashMap<>();
static {
products.put("iphone15",10);
products.put("MacBookPro",2);
products.put("giftCard",12);
}
public int getAmount(String productName){
return products.get(productName);
}
}
测试
public class App {
public static void main(String[] args) {
OrderProcessing orderProcessing = new OnlineShoppingOrder();
orderProcessing.processOrder("iphone15",17);
orderProcessing = new RestaurantOrder();
orderProcessing.processOrder("MacBookPro",1);
orderProcessing = new EcommerceOrder();
orderProcessing.processOrder("giftCard",2);
}
}

优点
- 代码复用性: 共享算法骨架,避免重复代码,促进代码复用。
- 扩展性: 允许子类实现或重写特定步骤,使得算法的部分行为可以灵活扩展。
- 维护性: 遵循开闭原则,允许在不修改算法整体结构的情况下修改部分步骤。
缺点
- 限制扩展性: 如果父类中的某些步骤对于所有子类都是固定的,可能会限制部分子类的扩展。
- 过多细节暴露: 子类必须了解父类的实现细节,可能导致对父类依赖过高。
策略模式的应用
Springboot 中 RestTemplate,RedisTemplate,RabbitTemplate等都是用模版方法。这里没有具体体现抽象类,可以理解为只有一个实现类的模版方法设计。
Spring Ioc
AbstractApplicationContext 定义了refresh的方法 这个方法相是算法的骨架
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 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);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 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) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
obtainFreshBeanFactory中两个方法都是抽象方法,子类实现具体刷新和获取beanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
