日常使用chatgpt - 时间校验 + 状态模式/策略模式扩展

189 阅读6分钟

需求

判断两个时间格式的入参是否满足条件

最终参考了答案1,但是根据实际需求进行了修改,没有使用源代码

本次回答最大的感受就是,gpt返回的代码真的是理性到了极致,既满足需求,判断逻辑也非常严谨

问1:

帮我写一段java代码,参数包括上架时间,下架时间,开始时间,开始时间必须介于其他两个时间之间,上架时间不能大于等于下架时间,所有的时间必须大于当前时间,如果条件不满足则抛出异常,时间的参数类型为LocalDateTime

答1:

import java.time.LocalDateTime;

public class TimeValidator {
    
    public static void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        if (onShelf.compareTo(offShelf) >= 0) {
            throw new Exception("上架时间不能晚于下架时间");
        }
        if (start.compareTo(onShelf) < 0 || start.compareTo(offShelf) > 0) {
            throw new Exception("开始时间必须介于上架时间和下架时间之间");
        }
        if (onShelf.compareTo(now) <= 0 || offShelf.compareTo(now) <= 0 || start.compareTo(now) <= 0) {
            throw new Exception("所有时间必须大于当前时间");
        }
    }
}

使用方法:

LocalDateTime onShelfTime = LocalDateTime.of(2021, 5, 1, 8, 0);
LocalDateTime offShelfTime = LocalDateTime.of(2021, 6, 1, 8, 0);
LocalDateTime startTime = LocalDateTime.of(2021, 5, 15, 12, 30);

try {
    TimeValidator.validate(startTime, onShelfTime, offShelfTime);
    // 时间符合要求,可以进行下一步操作
} catch (Exception e) {
    // 异常处理
    e.printStackTrace();
}

问2:

继续优化之前的代码,当前判断时间的逻辑不符合基础逻辑 感谢您指出问题。在实现代码之前,我会先理清楚需求,并进行一定的逻辑分析。

答2:

基于您的提醒和分析,我重新设计了 validate 方法的实现:

import java.time.LocalDateTime;

public class TimeValidator {
    
    public static void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        if (start.compareTo(now) <= 0 || onShelf.compareTo(now) <= 0 || offShelf.compareTo(now) <= 0) {
            throw new Exception("所有时间必须大于当前时间");
        }
        if (onShelf.compareTo(offShelf) >= 0) {
            throw new Exception("上架时间不能晚于下架时间");
        }
        if (start.compareTo(onShelf) < 0 || start.compareTo(offShelf) > 0) {
            throw new Exception("开始时间必须介于上架时间和下架时间之间");
        }
    }
    
}

具体优化如下:

先判断所有时间是否都大于当前时间,这是最基本的要求; 如果所有时间都大于当前时间,则进行其他的逻辑判断。


问3:

根据基础逻辑及算法优化,可以使用一个条件分支来判断时间是否满足要求,并通过 throw 抛出相应的异常信息。

答3:

以下是更加完善的代码实现:

import java.time.LocalDateTime;

public class TimeValidator {

    public static void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(start) || now.isAfter(onShelf) || now.isAfter(offShelf)) {
            throw new Exception("所有时间必须大于当前时间");
        } else if (onShelf.isAfter(offShelf)) {
            throw new Exception("上架时间不能晚于下架时间");
        } else if (start.isBefore(onShelf) || start.isAfter(offShelf)) {
            throw new Exception("开始时间必须介于上架时间和下架时间之间");
        }
    }

}

请注意,在该实现方式中,我们采用了一条较长的条件语句,但这样做不会影响程序的可读性和效率。


问4:

修改代码,将代码的逻辑优化为策略模式

答4:

好的,根据您提出的要求,我们可以将时间验证逻辑进行一定的重构,使用策略模式来实现。

在该模式下,我们可以定义一个时间验证接口 TimeValidateStrategy,并创建三个实现类,如下所示:

import java.time.LocalDateTime;

public interface TimeValidateStrategy {
    void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception;
}

在这里,我们只需要定义一个 validate 方法,然后在每个具体实现类中实现该方法即可。

现在,让我们先来看一下 AllAfterNowStrategy 策略的实现:

public class AllAfterNowStrategy implements TimeValidateStrategy {
    
    @Override
    public void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(start) || now.isAfter(onShelf) || now.isAfter(offShelf)) {
            throw new Exception("所有时间必须大于当前时间");
        }
    }

}

该策略用于判断所有时间是否都在当前时间之后。

接下来是 OnBeforeOffStrategy 策略的实现:

public class OnBeforeOffStrategy implements TimeValidateStrategy {

    @Override
    public void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        if (onShelf.isAfter(offShelf)) {
            throw new Exception("上架时间不能晚于下架时间");
        }
    }

}

该策略用于判断上架时间是否早于下架时间。

最后是 StartBetweenOnOffStrategy 策略的实现:

public class StartBetweenOnOffStrategy implements TimeValidateStrategy {

    @Override
    public void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        if (start.isBefore(onShelf) || start.isAfter(offShelf)) {
            throw new Exception("开始时间必须介于上架时间和下架时间之间");
        }
    }

}

该策略用于判断开始时间是否介于上架时间和下架时间之间。

接下来,我们需要一个上下文类 TimeValidator,它可以根据不同策略类型选择相应的验证方式:

import java.time.LocalDateTime;

public class TimeValidator {

    private TimeValidateStrategy allAfterNowStrategy = new AllAfterNowStrategy();
    private TimeValidateStrategy onBeforeOffStrategy = new OnBeforeOffStrategy();
    private TimeValidateStrategy startBetweenOnOffStrategy = new StartBetweenOnOffStrategy();

    public void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf, String... strategies) throws Exception {
        for (String strategy : strategies) {
            switch (strategy) {
                case "AllAfterNow":
                    allAfterNowStrategy.validate(start, onShelf, offShelf);
                    break;
                case "OnBeforeOff":
                    onBeforeOffStrategy.validate(start, onShelf, offShelf);
                    break;
                case "StartBetweenOnOff":
                    startBetweenOnOffStrategy.validate(start, onShelf, offShelf);
                    break;
                default:
                    throw new Exception("找不到该验证策略");
            }
        }
    }

}

在 validate 方法中,我们可以通过传入的参数选择相应的验证策略。如果用户需要执行多个验证策略,我们可以使用可变参数 String... strategies 来承接这些策略类型。

最后,您可以创建一个测试类来运行上述代码:

import java.time.LocalDateTime;

public class Test {

    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2021, 2, 23, 14, 20);
        LocalDateTime onShelf = LocalDateTime.of(2021, 2, 23, 15, 20);
        LocalDateTime offShelf = LocalDateTime.of(2021, 2, 24, 10, 0);

        TimeValidator validator = new TimeValidator();
        try {
            validator.validate(start, onShelf, offShelf, "AllAfterNow", "OnBeforeOff", "StartBetweenOnOff");
            System.out.println("时间验证通过");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

}

当所有时间均满足要求时,程序会输出“时间验证通过”。反之,程序将抛出对应异常信息


问5:

再来一个状态模式的

答5:

好的,下面是状态模式的实现。

首先,我们定义一个 TimeValidatorState 接口,用于表示不同的时间验证状态。该接口包含三个方法:allAfterNow()、onBeforeOff() 和 startBetweenOnOff(),分别对应着时间验证器的不同状态。


public interface TimeValidatorState {

    void allAfterNow(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception;

    void onBeforeOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception;

    void startBetweenOnOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception;

}

接下来,我们创建三个实现类 AllAfterNowState、OnBeforeOffState 和 StartBetweenOnOffState,用于实现不同的时间验证功能:


import java.time.LocalDateTime;

public class AllAfterNowState implements TimeValidatorState {

    @Override
    public void allAfterNow(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(start) || now.isAfter(onShelf) || now.isAfter(offShelf)) {
            throw new Exception("所有时间必须大于当前时间");
        }
    }

    @Override
    public void onBeforeOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }

    @Override
    public void startBetweenOnOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }
}
public class OnBeforeOffState implements TimeValidatorState {

    @Override
    public void allAfterNow(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }

    @Override
    public void onBeforeOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        if (onShelf.isAfter(offShelf)) {
            throw new Exception("上架时间不能晚于下架时间");
        }
    }

    @Override
    public void startBetweenOnOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }
}
public class StartBetweenOnOffState implements TimeValidatorState {

    @Override
    public void allAfterNow(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }

    @Override
    public void onBeforeOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        // do nothing
    }

    @Override
    public void startBetweenOnOff(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        if (start.isBefore(onShelf) || start.isAfter(offShelf)) {
            throw new Exception("开始时间必须介于上架时间和下架时间之间");
        }
    }
}

在 TimeValidator 类中,我们使用 currentState 表示时间验证器的当前状态。同时,我们定义了三个常量,表示时间验证器处于不同的状态。


import java.time.LocalDateTime;

public class TimeValidator {

    private TimeValidatorState currentState;

    private final TimeValidatorState allAfterNowState = new AllAfterNowState();
    private final TimeValidatorState onBeforeOffState = new OnBeforeOffState();
    private final TimeValidatorState startBetweenOnOffState = new StartBetweenOnOffState();

    public TimeValidator() {
        currentState = allAfterNowState;
    }

    public void setCurrentState(TimeValidatorState currentState) {
        this.currentState = currentState;
    }

    public void validate(LocalDateTime start, LocalDateTime onShelf, LocalDateTime offShelf) throws Exception {
        currentState.allAfterNow(start, onShelf, offShelf);
        setCurrentState(onBeforeOffState);
        currentState.onBeforeOff(start, onShelf, offShelf);
        setCurrentState(startBetweenOnOffState);
        currentState.startBetweenOnOff(start, onShelf, offShelf);
    }
}

可以看到,在 validate 方法中,我们按照不同的状态调用了不同的时间验证方法,从而实现了状态模式。

最后,您可以创建一个测试类来验证该时间验证器是否正常工作:


import java.time.LocalDateTime;

public class Test {

    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2021, 2, 23, 14, 20);
        LocalDateTime onShelf = LocalDateTime.of(2021, 2, 23, 15, 20);
        LocalDateTime offShelf = LocalDateTime.of(2021, 2, 24, 10, 0);

        // 创建时间验证器,并进行验证
        TimeValidator validator = new TimeValidator();
        try {
            validator.validate(start, onShelf, offShelf);
            System.out.println("时间验证通过");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

}

当所有时间均满足要求时,程序会输出“时间验证通过”。反之,程序将抛出对应异常信息。