工厂+模板模式介绍及实战

工厂+模板模式介绍及实战

1、设计模式介绍

1.1、工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

1.1.1、介绍

**意图:**定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

**主要解决:**主要解决接口选择的问题。

**何时使用:**我们明确地计划不同条件下创建不同实例时。

**如何解决:**让其子类实现工厂接口,返回的也是一个抽象的产品。

**关键代码:**创建过程在其子类执行。

应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

**缺点:**每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

**注意事项:**作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

1.2、模板模式

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

1.2.1、介绍

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

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

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

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

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

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

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

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

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

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

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 :
 * @date :Created in 10:23 2022/9/27
 * @description :
 * @version: 1.0
 */
public interface IRuleTypeFactory {

    /**
     * 获取接口类型
     * @Author 
     * @Date Created in 10:24 2022/9/27
     * @Description
     * @param ruleType 接口类型
     * @return com.cheche365.partner.service.impl.rule.type.BaseRuleType
     **/
    BaseRuleType getType(RuleType ruleType);

}

2.2.5、工厂RuleTypeFactoryImpl.java

/**
 * @author :
 * @date :Created in 10:28 2022/9/27
 * @description :
 * @version: 1.0
 */
@Service
public class RuleTypeFactoryImpl implements IRuleTypeFactory {

    @Resource(name = "siftType")
    private BaseRuleType siftType;
    @Resource(name = "quoteType")
    private BaseRuleType quoteType;
    @Resource(name = "automateType")
    private BaseRuleType automateType;
    @Resource(name = "insureType")
    private BaseRuleType insureType;

    private static Map<RuleType, BaseRuleType> typeMap = new HashMap<>();

    @PostConstruct
    public void intiRuleType() {
        typeMap.put(RuleType.sift, siftType);
        typeMap.put(RuleType.quote, quoteType);
        typeMap.put(RuleType.automate, automateType);
        typeMap.put(RuleType.insure, insureType);
    }

    @Override
    public BaseRuleType getType(RuleType ruleType) {
        return typeMap.get(ruleType);
    }
}

2.2.6、RuleManageServiceImpl.java

/**
 * @author :
 * @date :Created in 18:22 2022/9/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
    评论
好的,我了解了您的问题。下面是我对这个问题的回答: 首先,我们需要了解一下策略模式工厂模式模板方法模式的概念和用法: - 策略模式:将一组算法封装起来,使它们可以互相替换,从而使得算法的变化不会影响到使用算法的客户端。在策略模式中,我们需要定义一个策略接口和具体的策略实现类。 - 工厂模式:将对象的创建与使用分离,通过工厂类来创建对象,从而使得客户端无需知道对象的具体实现。在工厂模式中,我们需要定义一个工厂接口和具体的工厂实现类。 - 模板方法模式:将一组相似的算法步骤封装起来,使得算法的变化只会影响到模板方法的具体实现,从而使得代码的复用性和可维护性更好。 在实现不同支付方式的接口时,我们可以使用策略模式来实现不同的支付策略,工厂模式来创建不同的支付策略对象,模板方法模式来实现支付的公共流程。 具体实现步骤如下: 1. 定义支付策略接口 PaymentStrategy,其中包含一个 pay 方法用来实现支付功能。 ```java public interface PaymentStrategy { void pay(double amount); } ``` 2. 定义具体的支付策略实现类,例如 AlipayPaymentStrategy 和 WechatPaymentStrategy,实现 PaymentStrategy 接口中的 pay 方法。 ```java public class AlipayPaymentStrategy implements PaymentStrategy { @Override public void pay(double amount) { // 实现支付宝支付逻辑 System.out.println("使用支付宝支付:" + amount + "元"); } } public class WechatPaymentStrategy implements PaymentStrategy { @Override public void pay(double amount) { // 实现微信支付逻辑 System.out.println("使用微信支付:" + amount + "元"); } } ``` 3. 定义工厂接口 PaymentFactory,其中包含一个 createPayment 方法用来创建支付策略对象。 ```java public interface PaymentFactory { PaymentStrategy createPayment(); } ``` 4. 定义具体的支付工厂实现类,例如 AlipayPaymentFactory 和 WechatPaymentFactory,实现 PaymentFactory 接口中的 createPayment 方法。 ```java public class AlipayPaymentFactory implements PaymentFactory { @Override public PaymentStrategy createPayment() { return new AlipayPaymentStrategy(); } } public class WechatPaymentFactory implements PaymentFactory { @Override public PaymentStrategy createPayment() { return new WechatPaymentStrategy(); } } ``` 5. 定义支付模板类 PaymentTemplate,其中包含一个 pay 方法用来实现支付的公共流程,该方法调用 PaymentFactory 创建支付策略对象,并调用支付策略的 pay 方法实现支付功能。 ```java public abstract class PaymentTemplate { public void pay(double amount) { PaymentStrategy paymentStrategy = createPaymentStrategy(); paymentStrategy.pay(amount); } protected abstract PaymentStrategy createPaymentStrategy(); } ``` 6. 定义具体的支付模板类实现类,例如 AlipayPaymentTemplate 和 WechatPaymentTemplate,实现 PaymentTemplate 中的 createPaymentStrategy 方法,返回对应的支付策略对象。 ```java public class AlipayPaymentTemplate extends PaymentTemplate { @Override protected PaymentStrategy createPaymentStrategy() { return new AlipayPaymentFactory().createPayment(); } } public class WechatPaymentTemplate extends PaymentTemplate { @Override protected PaymentStrategy createPaymentStrategy() { return new WechatPaymentFactory().createPayment(); } } ``` 7. 在 SpringBoot 项目中使用支付模板类实现不同支付方式的接口,例如 PaymentController,其中包含一个 pay 方法用来接收支付请求,根据支付方式调用对应的支付模板类实现支付功能。 ```java @RestController public class PaymentController { @GetMapping("/pay") public String pay(@RequestParam("amount") double amount, @RequestParam("type") String type) { PaymentTemplate paymentTemplate = null; if ("alipay".equals(type)) { paymentTemplate = new AlipayPaymentTemplate(); } else if ("wechat".equals(type)) { paymentTemplate = new WechatPaymentTemplate(); } else { return "不支持的支付方式:" + type; } paymentTemplate.pay(amount); return "支付成功:" + amount + "元"; } } ``` 这样,我们就可以通过策略模式工厂模式模板方法模式来实现不同支付方式的接口,使得代码更加灵活、可维护性更好。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白de成长之路

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

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

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

打赏作者

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

抵扣说明:

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

余额充值