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

模板方法的概念:定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

概念

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

核心设计要点

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设计模式之模板方法详解

基础教程推荐