带关联参数校验的API查询Object builder实现方案及设计合理性咨询
问题1:可扩展的Builder实现方案
你要的构建阶段即可校验的Builder模式是存在的,行业内一般叫阶梯式Builder(类型安全Builder),核心思路是把参数的依赖规则拆成不同的构建步骤,每个步骤仅暴露当前允许调用的方法,开发者必须按合法流程完成参数填写,才能最终生成对象,不需要为每一种合法查询单独写构造函数,扩展性很强。
具体实现逻辑如下:
- 先梳理所有参数的依赖关系,把构建流程拆成多个节点:比如第一步必须先选择查询类型,选择
Key查询后,下一个节点仅暴露withId()必填参数设置方法,选择Group查询后仅暴露withGroupName()方法 - 为每个步骤定义单独的接口,每个接口仅返回下一个步骤的接口类型,Builder实现类实现所有步骤接口
- 只有完成所有必填参数设置后,才会进入可设置可选参数、最终调用
build()的节点
示例代码(Java语法为例,其他强类型语言逻辑一致):
// 构建第一步:选择查询类型 public interface QueryTypeStep { KeyQueryStep selectKeyQuery(); GroupQueryStep selectGroupQuery(); } // Key查询的必填参数步骤 public interface KeyQueryStep { OptionalParamStep withId(String id); } // Group查询的必填参数步骤 public interface GroupQueryStep { OptionalParamStep withGroupName(String groupName); } // 可选参数设置+最终构建步骤 public interface OptionalParamStep { OptionalParamStep withPageSize(int pageSize); OptionalParamStep withFilter(Map<String, Object> filter); APIQuery build(); } // Builder实现类 public class APIQueryBuilder implements QueryTypeStep, KeyQueryStep, GroupQueryStep, OptionalParamStep { private QueryType queryType; private String id; private String groupName; private int pageSize; private Map<String, Object> filter; // 构建入口仅返回第一步的接口,限制调用顺序 public static QueryTypeStep builder() { return new APIQueryBuilder(); } @Override public KeyQueryStep selectKeyQuery() { this.queryType = QueryType.KEY; return this; } @Override public GroupQueryStep selectGroupQuery() { this.queryType = QueryType.GROUP; return this; } @Override public OptionalParamStep withId(String id) { this.id = id; return this; } @Override public OptionalParamStep withGroupName(String groupName) { this.groupName = groupName; return this; } @Override public OptionalParamStep withPageSize(int pageSize) { this.pageSize = pageSize; return this; } @Override public OptionalParamStep withFilter(Map<String, Object> filter) { // 此处可直接加入参数关联校验,不符合要求可直接抛出编译提示或者异常 this.filter = filter; return this; } @Override public APIQuery build() { // 可加入兜底运行时校验,作为双保险 return new APIQuery(queryType, id, groupName, pageSize, filter); } }
实际使用时,开发者如果没有完成必填参数填写,根本无法调用build()方法,IDE会直接给出语法错误提示,完全符合你的需求。后续新增规则只要新增对应的步骤接口即可,原有逻辑不需要改动。
问题2:封装思路是否合理,是否属于过度设计
这个思路非常合理,完全不属于过度设计:
- 底层API不受你方控制,本身的参数约束复杂,且使用的开发者不了解API深层规则,如果不做封装,后续大概率会出现大量参数传错导致的空数据、脏数据问题,排查和修复成本远高于你现在做封装的成本
- 你做的封装相当于把API的隐性规则显性化到了SDK层面,后续规则变动只需要修改封装层即可,不需要通知所有使用的开发者同步更新知识,长期维护成本会低很多
- 额外做的编译期校验进一步降低了使用者的学习成本,哪怕是完全不了解API规则的开发者,跟着IDE的提示就能写出合法的请求,实用价值很高
可以额外补充一个优化点:在build()方法中加入兜底的运行时校验和日志打印,即使有没覆盖到的规则也能及时发现问题。
内容的提问来源于stack exchange,提问作者Nathan Bruissard
相关产品推荐
相关产品推荐

