模板+策略设计模式介绍及实战

模板+策略设计模式介绍及实战

1、设计模式介绍

1.1、模板模式

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

1.1.1、介绍

**意图:**定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

**主要解决:**一些方法通用,却在每一个子类都重新写了这一方法。

**何时使用:**有一些通用的方法。

**如何解决:**将这些通用算法抽象出来。

**关键代码:**在抽象类实现,其他步骤在子类实现。

应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。

优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。

**缺点:**每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。

**注意事项:**为防止恶意操作,一般模板方法都加上 final 关键词。

1.2、策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

1.2.1、介绍

**意图:**定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

**主要解决:**在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

**何时使用:**一个系统有许多许多类,而区分它们的只是他们直接的行为。

**如何解决:**将这些算法封装成一个一个的类,任意地替换。

**关键代码:**实现同一个接口。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

**注意事项:**如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

1.3、模板模式和策略模式的区别

  • 模板模式一般只针对一套算法,注重对同一个算法的不同细节进行抽象提供不同的实现。而策略模式注重多套算法多套实现,在算法中间不应该有交集,因此算法和算法只间一般不会有冗余代码!
  • 模板模式从头至尾,各个属性的位置都是固定的,是一个大而全的东西,固定了流程,按照模版来就行。各个抽象方法都是不重复的功能,有的渲染头部,有的选择底部。
  • 策略模式是针对同一个算法,有不同的实现(或多个算法多个实现)。各个策略完成的功能,同一时间,只能选择其中的一种,即互斥的。

2、模板+策略设计模式实战

2.1、业务场景介绍

对接第三方服务服务,一共涉及到6个接口,特点如下:

  • 六个接口路径不一致,
  • 请求方式方法一致,
  • 请求参数字段名称一样,
  • 响应结构体一致,响应内容不一致。

2.2、代码实现

2.2.0、RuleType枚举

/**
 * @Author 
 * @Date 2022/8/21 10:24
 * @Description 类型
 * @Version 1.0
 */
public enum RuleType {

    /**
     * @Author 
     * @Date Created in 17:15 2022/8/21
     * @Description 
     * @Param
     * @return
     **/
    sift,

    /**
     * image
     * @Author 
     * @Date Created in 16:58 2022/8/30
     * @Description
     * @param
     * @return
     **/
    quote,

    /**
     * automate
     * @Author YangYaNan
     * @Date Created in 11:57 2022/8/8
     * @Description
     * @param
     * @return
     **/
    automate;

}

2.2.1、抽象基类BaseRuleType.java

/**
 * @author :
 * @date :Created in 11:21 2022/8/15
 * @description :
 * @version: 1.0
 */
@Service
@Slf4j
public abstract class BaseRuleType {

    @Getter
    public RuleType ruleType;

    @Autowired
    List<BaseRuleApi> baseRuleApis;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RuleConfigRepo ruleConfigRepo;
    @Autowired
    QuoteRecordRepo quoteRecordRepo;


    /**
     * handlerRule核心逻辑
     * @Author YangYaNan
     * @Date Created in 19:13 2022/8/15
     * @Description
     * @param ruleDecorator 规则
     * @return void
     **/
    public abstract void handlerRule(IRuleDecorator ruleDecorator);

    /**
     * 解析规则结果
     * @Author 
     * @Date Created in 12:55 2022/8/8
     * @Description 目前使用
     * @param ruleDecorator 规则
     * @return java.lang.String
     **/
    public abstract void analyzeRuleData(IRuleDecorator ruleDecorator);

    /**
     * 挂载和ruleLog日志输出
     * @Author 
     * @Date Created in 14:40 2022/8/17
     * @Description
     * @param quoteProtocol 挂载属主
     * @param ruleDecorator 规则
     * @return void
     **/
    public abstract void mountAndPrintLog(QuoteProtocol quoteProtocol, IRuleDecorator ruleDecorator);

    /**
     * commonHandlerRule公共核心逻辑
     * @Author 
     * @Date Created in 19:13 2022/8/15
     * @Description
     * @param ruleDecorator
     * @return void
     **/
    public void commonHandlerRule(IRuleDecorator ruleDecorator){
        try {
            if (RuleInfoKey.RULE_NOT_GROUPID.equals(ruleDecorator.getRuleGroupId())) {
                log.info("[rule-{}-{}]不调用规则", ruleDecorator.getRuleType().toString(), ruleDecorator.getQuoteProtocol().getBusinessId());
                ruleDecorator.getRuleLog().setCallRule(false);
                return ;
            }
            baseRuleApis
                .stream()
                .filter(api -> api.supportType(ruleDecorator.getRuleType().toString()))
                .findFirst()
                .orElseThrow(() -> new CommonException(PARAMETER_ERROR.getCodeValue(), "暂不支持该类型规则"))
                .callRule(ruleDecorator);
            analyzeRuleData(ruleDecorator);
        }catch (Exception e) {
            log.error("[rule-{}-{}]调用规则异常:{},{}", ruleDecorator.getRuleType().toString(), ruleDecorator.getQuote().getBusinessId(), e.getMessage(), e.getStackTrace());
        }
    }

    void printLog(IRuleDecorator ruleDecorator) {
        ruleDecorator.getRuleLog().setEndAndConsumerTime(System.currentTimeMillis());
        log.info("[rule-{}-{}]ruleLog:{}", ruleDecorator.getRuleType().toString(), ruleDecorator.getQuote().getBusinessId(), CacheUtil.doJacksonSerialize(ruleDecorator.getRuleLog()));
    }

    public long getLongByInteger(Map dataMap, String ruleCoverageCode) {
        return dataMap.containsKey(ruleCoverageCode) ? ((Integer) dataMap.get(ruleCoverageCode)).longValue() : 1L;
    }

    public long getLongByDouble(Map dataMap, String ruleCoverageCode) {
        return dataMap.containsKey(ruleCoverageCode) ? ((Double) dataMap.get(ruleCoverageCode)).longValue() : 1L;
    }

    public double getDoubleByDouble(Map dataMap, String ruleCoverageCode) {
        return dataMap.containsKey(ruleCoverageCode) ? (Double) dataMap.get(ruleCoverageCode) : 1;
    }

    public double getDoubleByInteger(Map dataMap, String ruleCoverageCode) {
        return dataMap.containsKey(ruleCoverageCode) ? ((Integer) dataMap.get(ruleCoverageCode)).longValue() : 1;
    }

    public Object getObjectFromResultData(Map dataMap, String sendforinspectionLevel) {
        return dataMap.containsKey(sendforinspectionLevel) ? dataMap.get(sendforinspectionLevel) : "";
    }

    /**
     *  去掉首位逗号
     * @Author 
     * @Date Created in 16:26 2022/8/1
     * @Description
     * @param str 原字符串
     * @return java.lang.String
     **/
    public String startAndEndCommaRemove(String str) {
        String s = str.startsWith(",") ? str.replaceFirst(",", "") : str;
        return s.endsWith(",") ? s.substring(0, s.length() - 1) : s;
    }

    public boolean isValidNumber(String key) {
        String regx = "^\\d{4,6}$";
        boolean isNumber = Pattern.compile(regx).matcher(key).find();
        return isNumber;
    }

    void addAddActionRuleLog(RuleType.RuleTypeAction action, IRuleDecorator ruleDecorator, String ...changeInfoItems) {
        StringBuilder changeInfo = new StringBuilder();
        for (String s : changeInfoItems) {
            changeInfo.append(s).append("--");
        }
        ruleDecorator.addRuleLog(action.name(), changeInfo.toString());
    }


}

2.2.2、具体SiftType.java实现

/**
 * @author :
 * @date :Created in 11:24 2022/8/15
 * @description :
 * @version: 1.0
 */
@Service(value = "siftType")
@Slf4j
public class SiftType extends BaseRuleType {

    public SiftType(){
        this.ruleType = RuleType.sift;
    }

    @Override
    public void handlerRule(IRuleDecorator ruleDecorator) {
        commonHandlerRule(ruleDecorator);
    }

    /**
     * 解析规则返回data
     * @Author 
     * @Date Created in 11:56 2022/8/23
     * @Description 目前添加险种使用
     * @param ruleDecorator  报价
     * @return
     **/
    @Override
    public void analyzeRuleData(IRuleDecorator ruleDecorator){
        List<Suite> suites = ruleDecorator.getSuites();
        if (ObjectUtils.isEmpty(suites)){
            log.info("[rule-{}-{}]单交强不动态添加险种:{},{}", RuleType.sift.toString(), ruleDecorator.getQuoteProtocol().getBusinessId());
            return;
        }
        if (HttpStatus.HTTP_OK == ruleDecorator.getRuleResponse().getCode()) {
            HashMap<String, Boolean> ruleSupportSuitMap = RuleSupportSuitType.getRuleSupportSuitMap();
            suites.stream().forEach(suite -> { if (ruleSupportSuitMap.containsKey(suite.getCode())) { ruleSupportSuitMap.put(suite.getCode(), true); } });
            addSiftSuites(ruleDecorator, ruleSupportSuitMap);
            removeSiftSuites(ruleDecorator, ruleSupportSuitMap);
            updateSiftSuites(ruleDecorator, ruleSupportSuitMap);
            customizationSiftSuites(ruleDecorator, ruleSupportSuitMap);
        }
    }

    @Override
    public void mountAndPrintLog(QuoteProtocol quoteProtocol, IRuleDecorator ruleDecorator) {
        if (ObjectUtils.isNotEmpty(quoteProtocol.getBaseSuiteInfo()) && ObjectUtils.isNotEmpty(quoteProtocol.getBaseSuiteInfo().getBizSuiteInfo())) {
            quoteProtocol.getBaseSuiteInfo().getBizSuiteInfo().setSuites(ruleDecorator.getSuites());
            quoteProtocol.setSq(ruleDecorator.getSq());
        }
        printLog(ruleDecorator);
    }


    private void addSiftSuites(IRuleDecorator ruleDecorator, Map<String, Boolean> ruleSupportSuitMap) {
        //具体实现
    }

    private void customizationSiftSuites(IRuleDecorator ruleDecorator, Map<String, Boolean> ruleSupportSuitMap) {
        //具体实现
    }



    private void updateSiftSuites(IRuleDecorator ruleDecorator, HashMap<String, Boolean> ruleSupportSuitMap) {
        //具体实现
    }

    private void removeSiftSuites(IRuleDecorator ruleDecorator, HashMap<String, Boolean> ruleSupportSuitMap) {
        //具体实现
    }

}

2.2.3、具体AutomateType.java实现

/**
 * @author :
 * @date :Created in 11:28 2022/8/15
 * @description :
 * @version: 1.0
 */
@Service(value = "automateType")
@Slf4j
public class AutomateType extends BaseRuleType {

    public AutomateType() {
        this.ruleType = RuleType.automate;
    }

    @Override
    public void handlerRule(IRuleDecorator ruleDecorator) {
        commonHandlerRule(ruleDecorator);
    }

    @Override
    public void analyzeRuleData(IRuleDecorator ruleDecorator) {
        RuleResponse ruleResponse = ruleDecorator.getRuleResponse();
        String specialsStr= "";
        if (HttpStatus.HTTP_OK == ruleResponse.getCode()) {
            Map dataMap = ruleResponse.getData();
            specialsStr = dataMap.containsKey(RuleInfoKey.RULE_AUTOMATE_SPECIALLIST) ? dataMap.get(RuleInfoKey.RULE_AUTOMATE_SPECIALLIST).toString() : "";
            addAddActionRuleLog(RuleType.RuleTypeAction.add, ruleDecorator, specialsStr);
        }
        ruleDecorator.setSpecialInfos(specialsStr);
    }

    @Override
    public void mountAndPrintLog(QuoteProtocol quoteProtocol, IRuleDecorator ruleDecorator) {
        printLog(ruleDecorator);
    }


}

2.2.4、面向接口编程

/**
 * @author :YangYaNan
 * @date :Created in 18:20 2022/3/18
 * @description :规则统一service接口
 * @version: 1.0
 */
public interface IRuleManageService {

    /**
     * sift
     * @Author 
     * @Date Created in 17:20 2022/8/21
     * @Description
     * @param quoteProtocol 
     * @return QuoteProtocol
     **/
    QuoteProtocol riskChangeRuleInfo(QuoteProtocol quoteProtocol);
}

2.2.5、策略调用RuleManageServiceImpl.java

/**
 * @author :
 * @date :Created in 18:22 2022/8/18
 * @description :规则统一service层实现类
 * @version: 1.0
 */
@Service
@Slf4j
public class RuleManageServiceImpl implements IRuleManageService {

    @Autowired
    private List<BaseRuleType> baseRuleTypes;

    @Override
    public QuoteProtocol riskChangeRuleInfo(QuoteProtocol quoteProtocol) {
        IRuleDecorator ruleDecorator = new QuoteProtocolDecorator(quoteProtocol, RuleType.sift);
        BaseRuleType baseRuleType = baseRuleTypes.stream()
            .filter(api -> api.ruleType.equals(ruleDecorator.getRuleType()))
            .findFirst()
            .orElseThrow(() -> new CommonException(PARAMETER_ERROR.getCodeValue(), "暂不支持该类型"));
        baseRuleType.handlerRule(ruleDecorator);
        baseRuleType.mountAndPrintLog(quoteProtocol, ruleDecorator);
        return quoteProtocol;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot是一个用于创建独立的、基于Spring的应用程序的框架。在使用Spring Boot进行模板策略模式登录实战时,我们可以以下几个步骤来实现。 首先,创建一个User类,包含了用户的相关信息,例如用户名和密码等。 接下来,创建一个LoginStrategy接口,定义了登录策略模式中的登录方法。该接口应包含一个方法,用于验证用户的登录信息并返回登录结果。 然后,创建具体的登录策略类,实现LoginStrategy接口。根据需求,可以创建多个具体的登录策略类,每个类实现自己特定的验证逻辑。例如,可以创建UsernamePasswordLoginStrategy类,该类通过验证用户名和密码来验证用户的登录信息。 接着,创建一个LoginContext类,用于控制登录策略的选择和执行。该类应包含一个LoginStrategy类型的属性,用于保存当前使用的登录策略。该类还应提供一个setStrategy方法,用于设置当前的登录策略。在登录方法中,实际的登录操作应交给当前使用的登录策略类来完成。 最后,创建一个Spring Boot应用程序,配置相关的Web接口和视图,用于用户登录操作。在登录接口中,通过LoginContext类来选择并执行相应的登录策略。根据验证结果,可以返回相应的登录成功或失败信息。 总结来说,在使用Spring Boot进行模板策略模式登录实战时,我们需要创建一个User类、一个LoginStrategy接口、多个具体的登录策略类、一个LoginContext类和一个Spring Boot应用程序。通过这些组件的协作,我们可以实现基于模板策略模式的登录功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白de成长之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值