Java设计模式之模板模式

Java设计模式之模板模式

  • 1. 模板模式概述
    • 1.1 模板模式介绍
    • 1.2 模板模式类图
    • 1.3 模板方法模式的注意事项和细节
  • 2. 模板模式实现
    • 2.1 做菜模板模式
    • 2.2 银行办理业务模板模式
    • 2.3 银行办理业务函数式编程改造

1. 模板模式概述

1.1 模板模式介绍

1.模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 在一个抽象类公开定义了执行它的方法的模板。它的子类可以更需要重写方法实现,但可以成为典型类中定义的方式进行。
2.简单说,模板方法模式定义了一个操作中的算法的核心定义,而将一些步骤迟缓到子类中,模仿子类可以不改变一一个算法的结构,就可以重新定义该算法的部分特定步骤。
3.这些类型的设计模式属于行为型模式。

模板模式适用于通用步骤的操作,比如做菜,不管你是西红柿炒鸡蛋,还是土豆炖牛肉实现步骤都是一样的,备料,做菜,上菜。
再比如投放系统,不管你是投放巨量引擎,广点通还是百度,前期工作实现步骤也都是一样的,配置物料信息,构建投放对象,投放广告。

1.2 模板模式类图

Java设计模式之模板模式_第1张图片
对原理类图的说明-即(模板方法模式的角色及职责)
1.AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法。
2.ConcreteClass 实现抽象方法, 以完成算法中特点子类的步骤。

1.3 模板方法模式的注意事项和细节

  1. 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改.需要修改算法时,只要修改父类的模板方 法或者已经实现的某些步骤,子类就会继承这些修改
  2. 实现了最大化代码复用.父类的模板方法和已实现的某些步骤会被子类继承而直接使用.
  3. 既统一了算法,也提供了很大的灵活性.父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步 骤的实现.
  4. 该模式的不足之处:每个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
  5. 一般模板方法都加上 final 关键字, 防止子类重写模板方法.
  6. 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其 个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理

2. 模板模式实现

模板模式实现案例采用三种方式:
第一案例是做菜,无论做什么菜都是这三个步骤,备料,做菜,上菜,但是三个步骤都不相同,模板定义步骤流程,通过不同的子类继承抽象模板实现模板设计模式。

第二个案例是银行办理业务,无论办理什么业务都是取号,办理业务,评价。这里取号与评价都是相同的,各个子类只需要处理不同业务即可,通过不同的子类继承抽象模板实现模板设计模式。

第三个案例是银行办理业务的Java8函数式编程消费者模式Consumer模式改造,原理相同。

2.1 做菜模板模式

DishEggsWithTomato

package com.zrj.design.template.dish;

/**
 * 西红柿炒鸡蛋
 *
 * @author zrj
 * @since 2022/2/8
 */
public class DishEggsWithTomato extends DishTemplate {
    @Override
    public void preparation() {
        System.out.println("准备西红柿鸡蛋...");
    }

    @Override
    public void doing() {
        System.out.println("开始炒西红柿鸡蛋...");
    }

    @Override
    public void carriedDishes() {
        System.out.println("西红柿鸡蛋装盘...");
    }
}


DishOnionWithTofu

package com.zrj.design.template.dish;


/**
 * 小葱拌豆腐
 *
 * @author zrj
 * @since 2022/2/8
 */
public class DishOnionWithTofu extends DishTemplate {
    @Override
    public void preparation() {
        System.out.println("准备小葱豆腐...");
    }

    @Override
    public void doing() {
        System.out.println("开始炒小葱拌豆腐...");
    }

    @Override
    public void carriedDishes() {
        System.out.println("小葱拌豆腐装盘...");
    }
}



DishTemplate

package com.zrj.design.template.dish;

/**
 * 做菜模板类
 * 用于定义做菜的执行步骤,所有菜都可以按照这种方式做菜
 *
 * @author zrj
 * @since 2022/2/8
 */
public abstract class DishTemplate {
    /**
     * 做菜执行步骤
     */
    public final void doDish() {
        this.preparation();
        this.doing();
        this.carriedDishes();
    }

    /**
     * 备料
     */
    public abstract void preparation();

    /**
     * 做菜
     */
    public abstract void doing();

    /**
     * 上菜
     */
    public abstract void carriedDishes();

}



DishTemplateTest

package com.zrj.design.template.dish;


import org.junit.Test;

/**
 * 模板模式
 * 抽象父类定义方法模板,子类自定义实现方式。
 * 优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
 * 缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
 * 使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
 * 注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
 *
 * 使用场景很多,只要有相同的执行逻辑,或者重要的复杂的方法,都可以交给父类管理。
 * 比如开发XX系统步骤都是一样的,立项,需求,开发,测试,上线。
 *
 * @author zrj
 * @since 2022/2/8
 */
public class DishTemplateTest {
    @Test
    public void templateTest() {
        System.out.println("----------西红柿炒鸡蛋----------");
        DishTemplate eggsWithTomato = new DishEggsWithTomato();
        eggsWithTomato.doDish();

        System.out.println("----------小葱拌豆腐----------");
        DishTemplate onionWithTofu = new DishOnionWithTofu();
        onionWithTofu.doDish();
    }

}


2.2 银行办理业务模板模式

BankBusinessHandler

package com.zrj.design.template.bank;

import cn.hutool.core.util.RandomUtil;

/**
 * 模板方法设计模式的抽象类
 * 模板设计模式主要用来处理相同处理流程中的不同点,例如银行办理业务,无论什么业务,首先需要取号,其次处理业务,然后评价不同之处在于处理不同的业务使用不同的方式。
 * BankBusinessHandler作为抽象模板
 * BankSaveMoneyHandler作为存钱业务处理类,继承抽象模板BankBusinessHandler
 * BankDrawMoneyHandler作为理财业务处理类,继承抽象模板BankBusinessHandler
 *
 * @author zrj
 * @since 2022/2/8
 **/
public abstract class BankBusinessHandler {

    /**
     * 模板方法,执行器
     */
    public final void execute() {
        getNumber();
        handle();
        judge();
    }

    /**
     * 取号
     */
    private void getNumber() {
        System.out.println("取号:" + RandomUtil.randomNumbers(8));
    }

    /**
     * 办理业务
     */
    public abstract void handle();

    /**
     * 评价
     */
    private void judge() {
        System.out.println("评价:五星好评!");
    }

}

BankBusinessHandlerTest

package com.zrj.design.template.bank;

/**
 * 模板方法测试类
 *
 * @author zrj
 * @since 2022/2/8
 **/
public class BankBusinessHandlerTest {
    public static void main(String[] args) {

        //存钱业务处理
        BankSaveMoneyHandler bankSaveMoneyHandler = new BankSaveMoneyHandler();
        bankSaveMoneyHandler.execute();

        System.out.println("------------------------------");

        //理财业务处理
        BankDrawMoneyHandler bankDrawMoneyHandler = new BankDrawMoneyHandler();
        bankDrawMoneyHandler.execute();

    }
}

BankDrawMoneyHandler

package com.zrj.design.template.bank;

/**
 * 理财业务
 *
 * @author zrj
 * @since 2022/2/8
 **/
public class BankDrawMoneyHandler extends BankBusinessHandler {
    /**
     * 办理业务
     */
    @Override
    public void handle() {
        System.out.println("理财:2000$");
    }
}

BankSaveMoneyHandler

package com.zrj.design.template.bank;

/**
 * 存钱业务
 *
 * @author zrj
 * @since 2022/2/8
 **/
public class BankSaveMoneyHandler extends BankBusinessHandler {
    /**
     * 办理业务
     */
    @Override
    public void handle() {
        System.out.println("存钱:1000$");
    }
}

2.3 银行办理业务函数式编程改造

BankBusinessHandlerCustomer

package com.zrj.design.template.customer;

import cn.hutool.core.util.RandomUtil;

import java.math.BigDecimal;
import java.util.function.Consumer;

/**
 * 模板设计模式的抽象类
 * Java8函数式编程消费者模式Customer实现模板设计模式
 *
 * @author zrj
 * @since 2022/2/8
 **/
public class BankBusinessHandlerCustomer {
    /**
     * 存钱
     */
    public void save(BigDecimal amount) {
        execute(a -> System.out.println("存钱:" + amount));
    }

    /**
     * 理财
     */
    public void draw(BigDecimal amount) {
        execute(a -> System.out.println("理财:" + amount));
    }

    /**
     * 模板方法,执行器
     */
    public void execute(Consumer<BigDecimal> consumer) {
        getNumber();
        consumer.accept(null);
        judge();
    }

    /**
     * 取号
     */
    private void getNumber() {
        System.out.println("取号:" + RandomUtil.randomNumbers(8));
    }

    /**
     * 评价
     */
    private void judge() {
        System.out.println("评价:五星好评!");
    }
}

BankBusinessHandlerCustomerTest

package com.zrj.design.template.customer;

import java.math.BigDecimal;

/**
 * @author zrj
 * @since 2022/2/8
 **/
public class BankBusinessHandlerCustomerTest {
    public static void main(String[] args) {
        //构建银行业务处理对象
        BankBusinessHandlerCustomer businessHandler = new BankBusinessHandlerCustomer();

        //存钱业务处理
        businessHandler.save(new BigDecimal("3000"));

        System.out.println("------------------------------");

        //理财业务处理
        businessHandler.draw(new BigDecimal("6000"));

    }

}

你可能感兴趣的:(基础框架,模板设计模式)