【设计模式】实战篇

本文介绍了在农场工作流程中如何运用模板方法模式和策略模式进行代码优化,通过模板方法抽象出核心算法步骤,然后使用策略模式替换if-else条件,实现不同阶段的工作流程定制。
摘要由CSDN通过智能技术生成

【实战一】模板方法模式

模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

待优化的代码 -  模板方法模式

抽象类

定义一个抽象类:FarmWorkNodeRecord:表示其记录是用来操作计划的节点对象的。

public abstract class FarmWorkNodeRecordService  {

    // 模拟Mapper
    private String plantPlanRuleDifferenceThresholdService = "plantPlanRuleDifferenceThresholdService";
    private String plantPlanRuleInfoService = "plantPlanRuleInfoService";
    private String plantPlanInfoService = "plantPlanInfoService";

    /**
     * 模板方法
     */
    final void insertFarmWorkNodeRecordVo(String type){
        // 1. 插入当前记录
        insertFarmWorkNodeRecord();
        // 2. 插入土地
        insertBatchLand();
        // 3. 更新种植计划规则
        updatePlantPlanRule();
        // 4. 更新规则差值表
        calculatePlantPlanRuleDifferenceThreshold(type);
        // 5. 计划节点操作状态更新
        updateIfAccomplishNodeFarming(type);
    }
    
    /**
     * 插入当前记录
     */
    abstract void insertFarmWorkNodeRecord();
    /**
     * 插入土地
     */
    abstract void insertBatchLand();

    /**
     * 仅延迟种植计划当前的节点规则
     */
    void updateSelf(){
        System.out.println("3. "+ plantPlanRuleInfoService +"\t仅延迟种植计划当前的节点规则");
    }
    /**
     * 延迟种植计划当前节点以及后序的节点规则
     */
    void updateSelfAndChild(){
        System.out.println("3. "+ plantPlanInfoService +"\t延迟种植计划当前节点以及后序的节点规则");
    }
    /**
     *  更新规则差值表
     */
    void calculatePlantPlanRuleDifferenceThreshold(String nodeType){
        System.out.println("4. " + plantPlanRuleDifferenceThresholdService +"\t【" + nodeType + "】更新规则差值表");
    }
    /**
     * 计划节点操作状态更新: 父、 子
     */
    void updateIfAccomplishNodeFarming(String nodeType){
        System.out.println("5. " + plantPlanRuleInfoService +"\t【" + nodeType  + "】更新节点操作状态");
    }
    /**
     * 是否种植计划只延迟当前的结点规则
     * @return true更新当前; false 延迟当前以及
     */
    boolean isOnlyUpdateSelf() {
        return true;
    }

    /**
     * 更新种植计划规则
     *
     * <p>updateSelfAndChild
     * <ul>
     *    <li> 延迟种植计划当前节点以及后序的节点规则:
     *</ul>
     * <p>updateSelf
     * <ul>
     *    <li> 仅延迟种植计划当前的节点规则
     *</ul>
     *
     */
    final void updatePlantPlanRule(){
        if (isOnlyUpdateSelf()){
            updateSelf();
        }else {
            updateSelfAndChild();
        }
    }


}

下面解释一下,对这个抽象类类进行优化的思想:
「首先,先对业务操作高度抽象化,转化为模板方法」
我们先把 上图 「待优化的代码 - 模板方法模式」框住的代码高度抽象化,变为步骤3
image.png
「接下来,对模板方法的步骤进行分析」

  • 重复的代码,放到超类里面,统一进行管理
    • 普通方法
    • final 方法

image.png

  • 不重复的代码,交给子类进行重写
    • 抽象方法

image.png
「最后,通过钩子函数来决定到底调用哪个方法」
通过钩子函数:isOnlyUpdateSelf 来决定 步骤3updatePlantPlanRule 实际调用:updateSelf 或者 updateSelfAndChild
image.png

子类

子类BootStage实现:

public class FarmWorkNodeRecordBootStageServiceImpl extends FarmWorkNodeRecordService{

    // 模拟Mapper
    private String farmWorkRecordBootStageMapper = "farmWorkRecordBootStageMapper";
    private String farmWorkRecordBootStageLandMapper = "farmWorkRecordBootStageLandMapper";

    @Override
    void insertFarmWorkNodeRecord() {
        System.out.println("1. "+ farmWorkRecordBootStageMapper +"\t插入当前记录");
    }

    @Override
    void insertBatchLand() {
        System.out.println("2. "+ farmWorkRecordBootStageLandMapper +"\t插入土地");
    }

    
}

子类SprayStage实现:

public class FarmWorkNodeRecordSprayStageServiceImpl extends FarmWorkNodeRecordService{

    // 模拟代替Mapper
    private String farmWorkSprayStageMapper = "farmWorkSprayStageMapper";
    private String farmWorkRecordSprayStageLandMapper = "farmWorkRecordSprayStageLandMapper";


    @Override
    void insertFarmWorkNodeRecord() {
        System.out.println("1. "+ farmWorkSprayStageMapper +"\t插入当前记录");
    }

    @Override
    void insertBatchLand() {
        System.out.println("2. "+ farmWorkRecordSprayStageLandMapper +"\t插入土地");
    }
    
    /**
     * 重写钩子函数
     * @return
     */
    @Override
    boolean isOnlyUpdateSelf() {
        return false;
    }
}

此时,对于模板方法也就完毕了。测试看看:

1. farmWorkRecordBootStageMapper	插入当前记录
2. farmWorkRecordBootStageLandMapper	插入土地
3. plantPlanRuleInfoService	仅延迟种植计划当前的节点规则
4. plantPlanRuleDifferenceThresholdService	【BootStage】更新规则差值表
5. plantPlanRuleInfoService	【BootStage】更新节点操作状态

1. farmWorkSprayStageMapper	插入当前记录
2. farmWorkRecordSprayStageLandMapper	插入土地
3. plantPlanInfoService	延迟种植计划当前节点以及后序的节点规则
4. plantPlanRuleDifferenceThresholdService	【SprayStage】更新规则差值表
5. plantPlanRuleInfoService	【SprayStage】更新节点操作状态

❓但是,此时我们还没有解决我们在前面框住的代码。我们还需要解决如下的场景:
在这里插入图片描述

我是觉得简易工厂模式比较符合。
目前还没有想好说服自己到底用哪一个。
咕咕咕。另外我还剩下两个模式没有看完。忙得很啊。

ok,我最后采用的是策略模式 (2024年4月7日15:12:36)

【实战二】策略模式

使用策略模式消除冗长的if-else|记一次smart-auto重构总结

策略模式: 封装可互换的行为,然后使用委托来决定要采用哪一个行为

在上一步的时候,我们还没有实现解决如下场景:

我打算采用的是行为型模式中的 「策略模式」 ,主要考虑到这一部分主要是涉及到类和对象如何去交互以及分配职责的。

策略模式是出现次数最多的“劳模”了,就是定义一个 「抽象类」 ,加入 UpdateRule,声明为 「接口类型的实例变量」 , 这样每个对象都会在运行的时候动态的引用正确的行为 。

  1. 开始进行对FarmWorkNodeRecordService的方法 updatePlantPlanRule进行修改,变为updatePlantPlanRuleNew

(updatePlantPlanRule 相关的方法已废弃)

  1. 新增实例变量UpdateRule,声明为接口类型
  2. 让实例变量能够进行动态修改 setUpdateRule(UpdateRule updateRule)
  3. 具体的实现规则交由子类具体实现 updatePlantPlanRuleNew(String type)
  4. 为了避免 UpdateRule实例变量出现空指针异常的情况,重写了构造方法,默认了子类实现
public abstract class FarmWorkNodeRecordService {

    /**
     * todo 实例变量:用来指定如何更新种植计划规则
     */
    private UpdateRule updateRule;

    /**
     * 构造方法,实例变量默认交给 UpdateSelf (更新种植计划规则: 延迟种植计划当前的节点规则  0 1 都操作)
     */
    public FarmWorkNodeRecordService() {
        this.updateRule = new UpdateSelf();
    }

    /**
     * todo 对实例变化进行动态修改
     * @param updateRule 更新种植计划规则接口
     */
    public void setUpdateRule(UpdateRule updateRule){
        this.updateRule = updateRule;
    }

    /**
     * todo 更新种植计划规则,具体的实现规则交由子类具体实现
     * @param type 节点类型
     */
    public void updatePlantPlanRuleNew(String type){
        updateRule.updateRule(type);
    }

    // do something
}    
  1. 新增接口 UpdateRule
public interface UpdateRule {

    /**
     * 更新种植计划规则
     * @param type 节点类型
     */
    void updateRule(String type);
}
  1. 接口UpdateRule,不同的实现类实现接口中对 updateRule 更新种植计划规则 的实现:
  • UpdateSelf
  • UpdateSelfByOne
  • UpdateSelfByZero
  • UpdateSelfAndChild
  • UpdateSelfAndChildByOne
  • UpdateSelfAndChildByZero

下面是对部分的举例:

public class UpdateSelfByOne implements UpdateRule {
    // 模拟Mapper
    private String plantPlanRuleInfoService = "plantPlanRuleInfoService";

    @Override
    public void updateRule(String type) {
        System.out.println("3. 【"+ type + "】更新种植计划规则: 延迟种植计划当前的节点规则  1 操作");
        System.out.println("(1) "+ plantPlanRuleInfoService +"\t仅延迟种植计划当前的节点规则:1 ");
    }
}
public class UpdateSelfAndChild implements UpdateRule {

    private String plantPlanInfoService = "plantPlanInfoService";

    @Override
    public void updateRule(String type) {
        System.out.println("3. 【"+ type + "】延迟种植计划当前节点以及后序的节点规则: 0 1 都操作");
        System.out.println("(1) "+ plantPlanInfoService +"\t延迟种植计划当前节点以及后序的节点规则: 0 ");
        System.out.println("(2) "+ plantPlanInfoService +"\t延迟种植计划当前节点以及后序的节点规则: 1 ");
    }
}
  1. 不需要对 FarmWorkNodeRecordBootStageServiceImplFarmWorkNodeRecordSprayStageServiceImpl进行修改

  2. 测试类

public class TestDrive {
    public static void main(String[] args) {
        FarmWorkNodeRecordService bootStage = new FarmWorkNodeRecordBootStageServiceImpl();
        // 交给 子类UpdateSelfAndChild 实现具体的行为实现
        bootStage.setUpdateRule(new UpdateSelfAndChild());
        FarmWorkNodeRecordService sprayStage = new FarmWorkNodeRecordSprayStageServiceImpl();
        // 交给 子类UpdateSelfByOne 实现具体的行为实现
        sprayStage.setUpdateRule(new UpdateSelfByOne());
        bootStage.insertFarmWorkNodeRecordVo("BootStage");
        System.out.println();
        sprayStage.insertFarmWorkNodeRecordVo("SprayStage");
    }
}
  1. 查看输出结果
8. farmWorkRecordBootStageMapper	插入当前记录
9. farmWorkRecordBootStageLandMapper	插入土地
10. 【BootStage】延迟种植计划当前节点以及后序的节点规则: 0 1 都操作
(1) plantPlanInfoService	延迟种植计划当前节点以及后序的节点规则: 0 
(2) plantPlanInfoService	延迟种植计划当前节点以及后序的节点规则: 1 
11. plantPlanRuleDifferenceThresholdService	【BootStage】更新规则差值表
12. plantPlanRuleInfoService	【BootStage】更新节点操作状态

13. farmWorkSprayStageMapper	插入当前记录
14. farmWorkRecordSprayStageLandMapper	插入土地
15. 【SprayStage】更新种植计划规则: 延迟种植计划当前的节点规则  1 操作
(1) plantPlanRuleInfoService	仅延迟种植计划当前的节点规则:1 
16. plantPlanRuleDifferenceThresholdService	【SprayStage】更新规则差值表
17. plantPlanRuleInfoService	【SprayStage】更新节点操作状态

补充一下完整的FarmWorkNodeRecordService :其中,标注了 todo的 为本次补充或者修改的内容。

public abstract class FarmWorkNodeRecordService {

    /**
     * todo 实例变量:用来指定如何更新种植计划规则
     */
    private UpdateRule updateRule;

    // 模拟Mapper
    private String plantPlanRuleDifferenceThresholdService = "plantPlanRuleDifferenceThresholdService";
    private String plantPlanRuleInfoService = "plantPlanRuleInfoService";
    private String plantPlanInfoService = "plantPlanInfoService";

    /**
     * todo 构造方法,对实例变量默认为 UpdateSelf (更新种植计划规则: 延迟种植计划当前的节点规则  0 1 都操作)
     */
    public FarmWorkNodeRecordService() {
        this.updateRule = new UpdateSelf();
    }

    /**
     * todo 模板方法
     */
    final void insertFarmWorkNodeRecordVo(String type){
        // 1. 插入当前记录
        insertFarmWorkNodeRecord();
        // 2. 插入土地
        insertBatchLand();
        // 3. 更新种植计划规则 (更改)
        updatePlantPlanRuleNew(type);
        // 4. 更新规则差值表
        calculatePlantPlanRuleDifferenceThreshold(type);
        // 5. 计划节点操作状态更新
        updateIfAccomplishNodeFarming(type);
    }
    /**
     * 插入当前记录
     */
    public abstract void insertFarmWorkNodeRecord();
    /**
     * 插入土地
     */
    public abstract void insertBatchLand();


    /**
     * @deprecated todo 仅延迟种植计划当前的节点规则
     */
    @Deprecated
    void updateSelf(){
        System.out.println("3. "+ plantPlanRuleInfoService +"\t仅延迟种植计划当前的节点规则");
    }
    /**
     * @deprecated todo 延迟种植计划当前节点以及后序的节点规则
     */
    @Deprecated
    void updateSelfAndChild(){
        System.out.println("3. "+ plantPlanInfoService +"\t延迟种植计划当前节点以及后序的节点规则");
    }
    /**
     *  更新规则差值表
     */
    void calculatePlantPlanRuleDifferenceThreshold(String nodeType){
        System.out.println("4. " + plantPlanRuleDifferenceThresholdService +"\t【" + nodeType + "】更新规则差值表");
    }
    /**
     * 计划节点操作状态更新: 父、 子
     */
    void updateIfAccomplishNodeFarming(String nodeType){
        System.out.println("5. " + plantPlanRuleInfoService +"\t【" + nodeType  + "】更新节点操作状态");
    }

    /**
     * @deprecated todo 是否种植计划只延迟当前的结点规则
     * @return true更新当前; false 延迟当前以及
     */
    @Deprecated
    boolean isOnlyUpdateSelf() {
        return true;
    }

    /**
     *
     * @deprecated todo 更新种植计划规则
     *
     * <p> Use {@link FarmWorkNodeRecordService#updatePlantPlanRuleNew(String type)} instead.
     *
     *
     * <p>updateSelfAndChild
     * <ul>
     *    <li> 延迟种植计划当前节点以及后序的节点规则:
     *</ul>
     * <p>updateSelf
     * <ul>
     *    <li> 仅延迟种植计划当前的节点规则
     *</ul>
     */
    @Deprecated
    final void updatePlantPlanRule(){
        if (isOnlyUpdateSelf()){
            updateSelf();
        }else {
            updateSelfAndChild();
        }
    }

    /**
     * todo 对实例变化进行动态修改
     * @param updateRule 更新种植计划规则接口
     */
    public void setUpdateRule(UpdateRule updateRule){
        this.updateRule = updateRule;
    }

    /**
     * todo 更新种植计划规则,委托给子类具体实现
     * @param type 节点类型
     */
    public void updatePlantPlanRuleNew(String type){
            updateRule.updateRule(type);
    }

}
  • 我还想补充一个工厂方法模式的实战,看看有没有场景可以用到创建型的设计模式。
  • 等我整理一下笔记。 (2024年4月9日17:20:53——【设计模式】笔记篇
  • 我目前写的还只是java版本的,看看后续再结合到Springboot 项目里面。

还有三个小任务点。
革命还未成功,继续咕咕咕~~~

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值