Substitua à força
Definição do método de modelo:
Defina o esqueleto de um algoritmo em uma operação, adiando alguns passos para subclasses. O Método Modelo permite que as subclasses redefinam certos passos de um algoritmo sem alterar a estrutura do algoritmo.
Define o esqueleto de um algoritmo em uma operação, mas transfere algumas etapas do algoritmo para subclasses, permitindo que as subclasses redefinam certas etapas do algoritmo sem alterar a estrutura do algoritmo.
É um padrão comportamental.
Sobre o que está escrito isso? Não se preocupe, vamos supor primeiro um cenário e ver o que isso significa através do código.
Suponha:
Animal
A classe abstrata animal possui metabolism
o método do metabolismo, que é executado após três ações de comer(), beber() e dormir().
Pônei Pony
, bezerro Calf
Herança Animal
.
Diagrama de classes para este cenário hipotético:
Código
/**
* 模板方法设计模式
* 范式重写的方法,系统帮我们自动调用的
* 都可以称之为模板方法
*/
public class Main {
public static void main(String[] args) {
Animal pony = new Pony();
pony.metabolism();
}
}
abstract class Animal {
/**
* 新陈代谢
* 假设都需要经过吃、喝、睡
*/
public void metabolism() {
eat();
drink();
sleep();
}
abstract void eat();
abstract void drink();
abstract void sleep();
}
class Pony extends Animal {
@Override
void eat() {
System.out.println("Pony eating");
}
@Override
void drink() {
System.out.println("Pony drinking");
}
@Override
void sleep() {
System.out.println("Pony sleeping");
}
}
Se houver outro bezerro Calf
, também é um animal pequeno, e pode herdar naturalmente dele.E Animal
se o método de metabolismo do bezerro for chamado no método principal? Basta chamá-lo diretamente é feito, você não precisa chamar comer, beber e dormir um por um (chamado automaticamente no método do metabolismo).
class Calf extends Animal {
@Override
void eat() {
System.out.println("Calf eating");
}
@Override
void drink() {
System.out.println("Calf drinking");
}
@Override
void sleep() {
System.out.println("Calf sleeping");
}
}
transferir:
public static void main(String[] args) {
Animal pony = new Pony();
pony.metabolism();
System.out.println("------------------------");
Animal calf = new Calf();
calf.metabolism();
}
resultado da operação:
Pony eating
Pony drinking
Pony sleeping
------------------------
Calf eating
Calf drinking
Calf sleeping
Process finished with exit code 0
OK, o programa está concluído e eu usei o padrão de design do método de modelo !
Olhando para trás agora, a definição do método de modelo:
Define o esqueleto de um algoritmo em uma operação, mas transfere algumas etapas do algoritmo para subclasses, permitindo que as subclasses redefinam certas etapas do algoritmo sem alterar a estrutura do algoritmo.
小动物类Animal
的新陈代谢方法metabolism
就相当于一个算法骨架,我们的子类并没有改变算法(没有重写),只是对算法内部调用的方法继承下来,每个子类对这些特定步骤有自己的实现而已。
客户端调用的时候只需要调用骨架即可,具体的内部方法(eat、drink、sleep),系统会帮我们自动调用。
这种模式就是模板方法设计模式。
是的,我们一直在用它!
模板方法类图
这个时候,我们应该已经很熟悉模板方法了,类图很简单:
模板方法在Spring中的应用
1. JDBCTemplate
JDBCTemplate是Spring对JDBC的封装,开发人员自己写SQL,需要注入dataSource。
2. NamedParameterJdbcTemplate
也是基于JDBC的封装,不过在参数的书写上不使用 ?
占位符,而是使用 :参数名
的形式。
2. RestTemplate
RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
3. AmqpTemplate
AmqpTemplate接口定义了发送和接收消息的所有基本操作。
4. AbstractBeanFactory
下面提供一个简化版的 AbstractBeanFactory 抽象类,该类实现了获取实例的 getBean 方法,在方法 getBean 的实现过程中可以看到,主要是对单例 Bean 对象的获取以及在获取不到时需要拿到 Bean 的定义做相应 Bean 实例化操作。
getBean 并没有自身的去实现这些方法,而是只定义了调用过程以及提供了抽象方法,由实现此抽象类的其他类做相应实现。
/**
* 抽象类定义模板方法
* 继承了 DefaultSingletonRegistry ,也就具备了使用单例注册类方法
*
* @author 行百里者
* @date 2022-07-17 22:33
*/
public abstract class AbstractBeanFactory extends DefaultSingletonRegistry implements BeanFactory {
/**
* 获取实例
* 主要是对单例 Bean 对象的获取以及在获取不到时需要拿到 Bean 的定义做相应 Bean 实例化操作
* @param name 实例名称
* @return 实体类
* @throws BeansException 抛出 Bean 异常信息
*/
@Override
public Object getBean(String name) throws BeansException {
//获取单例类
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
//如果实体类为空,则创建实例(具备了创建实例的能力)
BeanDefinition beanDefinition = getBeanDefinition(name);
return createBean(name, beanDefinition);
}
/**
* 获取 Bean 定义
* 由实现此抽象类的其他类做相应的实现
* @param beanName Bean名称
* @return Bean 的定义信息
* @throws BeansException 抛出Bean异常
*/
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
/**
* 抽象方法:创建 Bean 实例
* 由实现此抽象类的其他类做相应的实现
* @param beanName Bean 名称
* @param beanDefinition Bean 的定义信息
* @return Bean 实体类
* @throws BeansException 抛出Bean异常
*/
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
总结模板方法的特点
通过上面的例子,我们可以看到,这种模式的优点:
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
当然我们也能看到,对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
以上。
点个赞再走吧~
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。