[Modo de design] Modo de modelo, aprenda e escreva um código elegante e robusto!

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:

AnimalA classe abstrata animal possui metabolismo método do metabolismo, que é executado após três ações de comer(), beber() e dormir().

Pônei Pony, bezerro CalfHeranç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 Animalse 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;
}

总结模板方法的特点

通过上面的例子,我们可以看到,这种模式的优点:

  • 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
  • 它在父类中提取了公共的部分代码,便于代码复用。
  • 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

当然我们也能看到,对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。

以上。

点个赞再走吧~

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

Acho que você gosta

Origin juejin.im/post/7121543775133892644
Recomendado
Clasificación