今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

模版模式(Template Pattern)

定义

模板方法是一种行为设计模式,它定义了一个算法的骨架,将某些步骤的具体实现推迟到子类中。这种模式允许在不改变算法整体结构的情况下,通过子类重写方法来修改算法的某些步骤。

意图

定义算法骨架: 定义一个算法的主要结构,将具体步骤的实现延迟到子类中。

允许扩展特定步骤: 允许子类根据需要重写或扩展父类中的特定步骤,同时保持整体算法结构不变。

参与者(角色)​​​​​​

  • 抽象类(Abstract Class):定义算法的抽象骨架,包含算法中的各个步骤的框架和顺序,但留下某些步骤的实现细节由子类实现。定义了模板方法,作为算法骨架的整体结构。
  • 具体类(Concrete Class):实现抽象类中的抽象方法,完成具体的算法细节。实现父类中定义的模板方法,覆盖或扩展算法中的特定步骤。

举例

已创建订单为例

类图:

 

这个例子中对应类的角色如下:

  • 抽象类(Abstract Class):OrderProcessing

  • 具体类(Concrete Class):OnlineShoppingOrder,RestaurantOrder,EcommerceOrder

 

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);
    }
}

 

优点

  1. 代码复用性: 共享算法骨架,避免重复代码,促进代码复用。
  2. 扩展性: 允许子类实现或重写特定步骤,使得算法的部分行为可以灵活扩展。
  3. 维护性: 遵循开闭原则,允许在不修改算法整体结构的情况下修改部分步骤。

缺点

  1. 限制扩展性: 如果父类中的某些步骤对于所有子类都是固定的,可能会限制部分子类的扩展。
  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();
}

分享到:

专栏

类型标签

网站访问总量