Java设计模式之模板方法详解

 更新时间:2022年07月26日 15:13:05   作者:kaico2018  
模板方法的概念:定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

概念

模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术,没有关联关系。因此,在模板方法模式的类结构图中,只有继承关系。

核心设计要点

AbstractClass:抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。

ConcreteClass:实现实现父类所定义的一个或多个抽象方法。。

优缺点

优点

  • 利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
  • 将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
  • 把不变的行为写在父类.上,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。

缺点

类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加,复杂性增加。类数量的增加,间接地增加了系统实现的复杂度。继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一-遍。

应用场景

  • 父类视角:一次性实现一个算法不变的部分,并将可变部分留给子类实现;
  • 子类视角:各个子类中,公共部分被提取出来,集中到一个公共的父类中,避免代码重复;

模板方法模式的目的是让子类可以扩展或具体实现固定方法的某个具体的步骤;对于模板来说,是一套固定的算法 ,通过子类可以扩展固定算法中某些算法步骤。

模板方法和策略模式的区别

策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。还有一种模

式也是关注对算法的封装一模版方法模式,对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类

Context,它与模版方法模式的区别在于:在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主

体则是封装到了封装类Context中,抽象策略Strategy一般是一个接口, 目的只是为了定义规范,里面一般不包含逻辑。其实,这只是通用实现,而在实际编程中,因为各个具体策略实现类之间难免存在–些相同的逻辑,为了避免重复的代码,我们常常使用抽象类来担任Strategy的角色,在里面封装公共的代码,因此,在很多应用的场景中,在策略模式中- -般会看到模版方法模式的影子。

代码案例

模版方法抽象类

@Slf4j
public abstract class AbstractPayCallbackTemplate {
    /**
     * 异步回调业务
     *
     * @return
     */
    public String asyncCallBack() {
        // 1. 支付回调验证参数
        Map<String, String> verifySignatureMap = verifySignature();
        // 2. 参数验证成功,写入日志中..
        payLog(verifySignatureMap);
        String analysisCode = verifySignatureMap.get("analysisCode");
        if (!analysisCode.equals("200")) {
            return resultFail();
        }
        // 3. 执行回调异步相关逻辑
        return asyncService(verifySignatureMap);
    }
    /**
     * 支付回调验证参数
     *
     * @return
     */
    protected abstract Map<String, String> verifySignature();
    /**
     * 使用多线程异步写入日志
     *
     * @param verifySignatureMap
     */
    @Async
    void payLog(Map<String, String> verifySignatureMap) {
        log.info(">>>>>>>>>>第二步 写入payLog........");
    }
    /**
     * 每个子类需要实现 实现业务解析操作
     *
     * @return
     */
    protected abstract String asyncService(Map<String, String> verifySignatureMap);
    /**
     * 异步返回结果..
     *
     * @return
     */
    protected abstract String resultSuccess();
    /**
     * 异步返回失败
     *
     * @return
     */
    protected abstract String resultFail();
}

具体实现模版类

@Log4j2
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
        //>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
        log.info(">>>>>第一步 解析支付宝据报文.....verifySignature()");
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "1399");
        verifySignature.put("orderDes", "充值永久会员");
        // 支付状态为1表示为成功....
        verifySignature.put("aliPayMentStatus", "1");
        verifySignature.put("aliPayOrderNumber", "201910101011");
        // 解析报文是否成功 200 为成功..
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }
    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
        String paymentStatus = verifySignatureMap.get("aliPayMentStatus");
        if (paymentStatus.equals("1")) {
            String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
            log.info(">>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...");
        }
        return resultSuccess();
    }
    @Override
    protected String resultSuccess() {
        return "ok";
    }
    @Override
    protected String resultFail() {
        return "fail";
    }
}
@Slf4j
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
        //>>>>假设一下为银联回调报文>>>>>>>>>>>>>>>>
        log.info(">>>>>第一步 解析银联数据报文.....verifySignature()");
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "1399");
        verifySignature.put("orderDes", "充值永久会员");
        // 支付状态为1表示为成功....
        verifySignature.put("paymentStatus", "1");
        verifySignature.put("orderNumber", "201910101011");
        // 解析报文是否成功 200 为成功..
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }
    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
        String paymentStatus = verifySignatureMap.get("paymentStatus");
        if (paymentStatus.equals("1")) {
            String orderNumber = verifySignatureMap.get("orderNumber");
            log.info(">>>>orderNumber:{orderNumber},已经支付成功 修改订单状态为已经支付...");
        }
        return resultSuccess();
    }
    @Override
    protected String resultSuccess() {
        return "success";
    }
    @Override
    protected String resultFail() {
        return "fail";
    }
}

工厂模式获取模版

public class TemplateFactory {
    private final static Map<String, AbstractPayCallbackTemplate> templateMap = new ConcurrentHashMap<>();
    static {
        templateMap.put("aliPay", new AliPayCallbackTemplate());
        templateMap.put("unionPay", new UnionPayCallbackTemplate());
    }
    public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId) {
        AbstractPayCallbackTemplate payCallbackTemplate = (AbstractPayCallbackTemplate) templateMap.get(templateId);
        return payCallbackTemplate;
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        AbstractPayCallbackTemplate aliPay = TemplateFactory.getPayCallbackTemplate("aliPay");
        String s = aliPay.asyncCallBack();
        System.out.println(s);
    }
}

到此这篇关于Java设计模式之模板方法详解的文章就介绍到这了,更多相关Java模板方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java文件写入器FileWriter使用指南

    Java文件写入器FileWriter使用指南

    在Java中,FileWriter类用于将字符写入文件中,它继承了Writer类,因此可以使用Writer类中的所有方法,下面我们就来深入探讨一下FileWriter类的使用方法吧
    2023-10-10
  • Mybatis映射文件规则实例详解

    Mybatis映射文件规则实例详解

    在映射文件当中,mapper元素是映射文件的根元素,其他的标签都是它的子元素,下面这篇文章主要给大家介绍了关于Mybatis映射文件规则的相关资料,需要的朋友可以参考下
    2022-04-04
  • 利用POI生成EXCEL文件的方法实例

    利用POI生成EXCEL文件的方法实例

    Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能,下面这篇文章主要给大家介绍了关于利用POI生成EXCEL文件的相关资料,需要的朋友可以参考下
    2018-07-07
  • Mysql存储java对象实例详解

    Mysql存储java对象实例详解

    这篇文章主要介绍了Mysql存储java对象实例详解的相关资料,需要的朋友可以参考下
    2016-11-11
  • 选择Spring Boot项目的内嵌容器的理由

    选择Spring Boot项目的内嵌容器的理由

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。这篇文章主要介绍了选择Spring Boot项目的内嵌容器,需要的朋友可以参考下
    2017-11-11
  • 详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则

    在本文里我们给大家详细分享了关于java内部类的访问格式和规则知识点内容,有兴趣的朋友们学习下。
    2018-10-10
  • java中Hashmap的get方法使用

    java中Hashmap的get方法使用

    这篇文章主要介绍了java中Hashmap的get方法使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Spring中的@EnableWebSecurity注解详解

    Spring中的@EnableWebSecurity注解详解

    这篇文章主要介绍了Spring中的@EnableWebSecurity注解详解,EnableWebSecurity注解是个组合注解,它的注解中,又使用了@EnableGlobalAuthentication注解,需要的朋友可以参考下
    2023-12-12
  • java随机生成10位数的字符串ID

    java随机生成10位数的字符串ID

    这篇文章主要为大家详细介绍了java随机生成10位数字符串ID的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • WebService教程详解(二)

    WebService教程详解(二)

    这篇文章主要介绍了WebService教程详解(二) 的相关资料,需要的朋友可以参考下
    2016-03-03

最新评论