模板方法模式

根据实际案例解释模板方法模式

  1. 案例: 生产不同口味的豆浆,现有"红豆",“黄豆”,"绿豆"三种不同口味,虽然口味不同但是生产豆浆的步骤是相同的,选择豆子- - ->添加配料- - - >浸泡豆子- - ->打碎生成豆浆
  2. 模板方法模式属于行为型模式,将某个功能的实现步骤骨架定义到一个公共的父类模板方法中,将每个步骤的细节延迟到子类,根据需求进行具体实现,可以更改步骤中的细节,但整体流程不可以更改(好像刚好与建造者模式反过来)

代码示例

生产豆浆案例

  1. 抽象出公共父类,根据功能实现步骤的执行流程定义模板方法,提供抽象或默认的每个步骤的方法,供具体产品子类继承,重写
abstract class Production{
	
	//模板方法(由于生产豆浆的流程步骤相同)
	//根据执行流程定义模板方法,客户端生产豆浆时
	//只需要调用模板方法即可
	public void productionRun() {
		select();
		add();
		soak();
		broken();
	}
	
	//每个步骤的细节(如果不同种类的豆浆在当前某个步骤中操作
	//方式一样则提供默认方法即可,若不一样,提供抽象方法
	//子类根据需求进行重写
	//选择豆子
	public void select() {
		System.out.println("选择当季豆子作为原材料");
	};
	//调价调料
	public void add() {
		System.out.println("向豆子中添加调料");
	};
	//浸泡
	abstract void soak();
	//打碎生成豆浆
	abstract void broken();
}
  1. 创建具体产品子类,子类继承抽象父类,根据每个步骤的细节不同重写父类中的方法
//黄豆
class YelloBean extends Production{
	//重写浸泡步骤
	@Override
	public void soak() {
		System.out.println("黄豆需要浸泡三个小时");
	}
	//重写打碎步骤
	@Override
	public void broken() {
		System.out.println("打碎黄豆需要10分钟");
	}
	
}
//红豆
class RedBean extends Production{
	@Override
	public void soak() {
		System.out.println("红豆需要浸泡两个小时");
	}

	@Override
	public void broken() {
		System.out.println("打碎红豆需要5分钟");
	}
}
  1. 客户端调用测试
public class Test {
	public static void  main(String[]args) {
		//生产黄豆豆浆
		Production yProduction = new YelloBean();
		//调用模板方法
		yProduction.productionRun();
		
		//生产红豆豆浆
		Production rProduction = new RedBean();
		rProduction.productionRun();
	}
}

模板方法中的钩子方法

假设定义的模板方法中,的某个步骤,在某些产品中不执行,在模板类中添加返回Boolean值的钩子方法,具体产品子类根据需求实现钩子方法,返回真假,在模板方法中通过钩子方法判断是否执行某个步骤

  1. 定义了模板的抽血父类(只关注钩子方法)
abstract class Production{
	
	//模板方法(由于生产豆浆的流程步骤相同)
	//根据执行流程定义模板方法,客户端生产豆浆时
	//只需要调用模板方法即可
	public void productionRun() {
		select();
		//通过钩子方法来确定是否执行某个步骤
		if(customerWantAdd()) {
			add();
		}
		soak();
		broken();
	}
	
	//每个步骤的细节(如果不同种类的豆浆在当前某个步骤中操作
	//方式一样则提供默认方法即可,若不一样,提供抽象方法
	//子类根据需求进行重写
	//选择豆子
	public void select() {
		System.out.println("选择当季豆子作为原材料");
	};
	//调价调料
	public void add() {
		System.out.println("向豆子中添加调料");
	};
	//浸泡
	abstract void soak();
	//打碎生成豆浆
	abstract void broken();
	
	//返回布尔值的钩子方法,通过返回的真假确定模板方法中的某个步骤是否执行
	abstract Boolean customerWantAdd();
}
  1. 具体产品
//黄豆
class YelloBean extends Production{

	@Override
	public void soak() {
		System.out.println("黄豆需要浸泡三个小时");
	}

	@Override
	public void broken() {
		System.out.println("打碎黄豆需要10分钟");
	}

	//重写钩子方法返回true
	@Override
	Boolean customerWantAdd() {
		return true;
	}
	
}

不添加调料的纯豆浆(关注钩子方法)

//纯豆浆,不添加糖
class PureBean extends Production{

	@Override
	public void soak() {
		System.out.println("纯豆浆黄豆需要浸泡三个小时");
	}

	@Override
	public void broken() {
		System.out.println("纯豆浆打碎黄豆需要10分钟");
	}

	//重写钩子方法返回 false
	@Override
	public Boolean customerWantAdd() {
		return false;
	}
	
}
  1. 调用时,如果生产纯豆浆,在执行模板方法时,调用纯豆浆里面重写的钩子方法,返回为false,模板方法中则不执行add()方法,另外抽象父类中提供的空方法,供子类根据需求,选择是否重写实现,这种也可以称为钩子方法

Spring 中模板方法的使用案例

在 Spring IOC 容器初始化用到了模板方法模式,查看 ConfigurableApplicationContext 接口 中的 refresh() 方法,继续向下查看该接口的实现类AbstractApplicationContext,中重写了 refresh() 方法,该方法就是一个模板方法,而AbstractApplicationContext就是一个公共的抽象父类,该类中定义了抽象方法,供子类实现,在refresh()方法中执行模板方法时调用的某些方法,就是通过子类实现例如下面的子类ClassPathXmlApplicationContext
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值