您现在的位置是:首页 >技术教程 >真实业务场景使用-门面模式(外观)设计模式网站首页技术教程
真实业务场景使用-门面模式(外观)设计模式
1.前言
最近接到要修改的业务功能,这个业务增删改查很多功能都需要校验时间,比如:
1.失效时间不能超过自己父表的失效时间,
2.失效时间不能是当前时间
3.失效时间不能早于生效时间
类似这样的不同的判断还有很多,我就先举这三种例子,因为这是在一个管理功能,也许未来还有很多的这样的规则处理,所以需要好好的设计下。
2.设计实现
我想着对于这种校验是一种规则,而对于时间的校验就是时间校验规则,所以我们定义个接口,某某业务时间规则接口,并定义了两个方法,一个是对传过来的两个时间的校验范围,一个是对当前时间及另一个传输过来的时间校验范围,如下伪代码
public interface XxBussinessDateRule{
/**
传入两个时间进行校验
*/
boolean dateScopeValidate(String dateOne,String dateTwo,MathSymbolsEnum mathSymbols);
/**
传入时间与当前时间进行校验
*/
boolean dateScopeValidateByCurrent(String date,MathSymbolsEnum mathSymbols);
}
MathSymbolsEnum枚舉類是专门处理数学符号的,如大于(>),小于(<),小于等于(<=)等等等等,
传输这个值才能更灵活处理校验规则。
public enum MathSymbolsEnum{
/**
大于
*/
GREATER_THAN,
/**
小于
*/
LESS_THAN,
/**
小于等于
*/
EQUAL_OR_LESS_THAN,
/**
大于等于
*/
EQUAL_OR_GREATER_THAN,
/**
等于
*/
EQUAL,
/**
不等于
*/
NOT_EQUAL,
}
DefaultxxBussinessRule类:是xxBussinessRule的实现类,因为只有此一个实现类,所以名称里加一个Default,这个类主要是对时间的校验,需要根据枚举类的符号进行判断,如果大于就调用此类私有方法dateValidateGreaterThan,如果小于就找私有方法dateValidateLessThan,用于处理不同情况的校验。
在我原有的实现里,这里调用的是不同工具类的处理方法。伪代码呢就直接写死true,False返回,你可随意实现
@Component
public class DefaultxxBussinessDateRule implements XxBussinessDateRule {
/**
* 传入两个时间进行校验
*/
@Override
public boolean dateScopeValidate(String dateOne, String dateTwo, MathSymbolsEnum mathSymbols) {
// 大于
if (mathSymbols.name().equals("GREATER_THAN")) {
return dateValidateGreaterThan(dateOne, dateTwo);
}
// 小于
if (mathSymbols.name().equals("LESS_THAN")) {
return dateValidateLessThan(dateOne, dateTwo);
}
return false;
}
/**
* 传入时间与当前时间进行校验
*/
@Override
public boolean dateScopeValidateByCurrent(String date, MathSymbolsEnum mathSymbols) {
// 小于等于
if (mathSymbols.name().equals("EQUAL_OR_LESS_THAN")) {
System.out.println("模拟校验:是否小于等于");
return true;
}
return false;
}
private boolean dateValidateGreaterThan(String dateOne, String dateTwo) {
// 模拟校验规则
// 假如第一个时间大于第二个时间
System.out.println("模拟校验:是否大于");
return true;
}
private boolean dateValidateLessThan(String dateOne, String dateTwo) {
// 模拟校验规则
// 假如第一个时间小于第二个时间
System.out.println("模拟校验:是否小于");
return true;
}
}
正常到这里就结束了,但是又考虑了下,未来如果这个功能又要加其他规则呢,和本次时间规则毫无关系呢,那就又需要新建接口,定义新的方法,ok没有问题,问题是如果再继续新加接口、定义方法呢,有这么多类都是这个功能下的规则,入口却是多个,业务逻辑也许并不相通,怎么办?
所以,加个类,这个类用来封装统一调用不同的入口使用,这个想法思路也叫门面模式(外观模式)。
门面模式:不想让用户调用更繁杂的方法,也不用让用户了解内部具体的实现,只要简单一调用就可实现方法即可。
新建统一门面类:XxBussnissRule,继承了基础的校验规则类(下面有讲),依赖业务时间类,并定义实现两个方法,这两个方法调用到了时间校验类里的规则,这样所有的调用方都以这个为入口,都调用到这里
@Component
public class XxBussnissRule extends BaseValidateRule{
@Resourcce
private XxBussinessDateRule xxBussinessDateRule;
public boolean dateScopeValidate(String dateOne,String dateTwo,MathSymbolsEnum mathSymbols){
return xxBussinessDateRule.dateScopeValidate(dateOne,dateTwo,mathSymbols);
}
public boolean dateScopeValidateByCurrent(String date,MathSymbolsEnum mathSymbols){
return xxBussinessDateRule.dateScopeValidateByCurrent(date,mathSymbols);
}
}
加了这个统一的入口,调用就很方便了,未来添加别的规则,只要在这个类里添加即可。
除了这一点以外,我们可能会有些通用规则,对于入参可能会有判空、校验入参字段长度啊等等一些基础规则,那么我们需要新建类:BaseValidateRule
这样,XxBussnissRule就可以继承BaseValidateRule类,用户调用XxBussnissRule就自然有了基础规则的功能。
public class BaseValidateRule{
// 举例...
public boolean isLength(){
return true;
}
}
3.测试准备
测试使用,单元测试调用业务规则校验时间伪代码,可以看到,我们使用统一的类调用即可,外部引用则可以直接引用这一个类,未来扩展其他规则,还可以依赖这个入口。
@SpringBootTest
public class TestApi {
@Resource
private XxBussnissRule xxBussnissRule;
@Test
public void testFaced() {
boolean dateValidate = xxBussnissRule.dateScopeValidate("2023-05-02", "20233-05-04", MathSymbolsEnum.GREATER_THAN);
boolean dateValidateByCurrent = xxBussnissRule.dateScopeValidateByCurrent("2023-05-17", MathSymbolsEnum.LESS_THAN);
System.out.println("两个日期校验比对模拟:"+dateValidate);
System.out.println("与当前日期校验比对模拟:"+dateValidateByCurrent);
}
}
执行结果,证明流程走下來了。