编程模式选型咨询:类前置校验方案对比与实例选择机制合理性
前置校验类实现方案对比与工厂方法实践解析
一、两个校验方案哪个更优?
咱们先拆解下两个方案的设计思路,再对比优劣:
方案1:校验类负责准入,返回有效业务实例
class Check { public UpdateClass check(Status status) { if (CheckFunc(status)) { // 校验通过才返回可用的业务类实例 return new UpdateClass(); } // 校验不通过可返回null或抛出异常,明确告知调用者 return null; } class UpdateClass { public void func1() { // 专注执行业务逻辑,无需关心校验 } // 其他业务方法... } }
这个方案的核心是把校验逻辑和业务逻辑彻底分离:
- 优点:
- 遵循单一职责原则:
UpdateClass只需要聚焦自身业务逻辑,不用掺杂校验代码,代码简洁易维护。 - 保证实例有效性:调用者拿到的
UpdateClass实例一定是通过校验的,不会出现调用方法却因未校验通过而无动作的隐性问题。 - 校验逻辑集中管理:后续校验规则变更时,只需修改
Check类,无需改动业务类代码。
- 遵循单一职责原则:
- 小局限:如果后续有多个业务类需要类似校验,可能需要扩展
Check类的逻辑,但整体可控。
方案2:业务类内置校验标记,每个方法判断
class UpdateClass { boolean passedCheck = false; public UpdateClass(Status status) { if (checkFunc(status)) { this.passedCheck = true; } } public void func1() { if (this.passedCheck) { // 执行业务逻辑 } } // 其他方法... }
这个方案把校验和业务逻辑揉在了一起:
- 缺点:
- 违反单一职责:
UpdateClass既要处理业务,又要管理校验,代码耦合度高,后续修改校验或业务逻辑容易互相影响。 - 存在无效实例:可能创建出
passedCheck=false的实例,调用者调用方法时无任何反馈,这种隐性失败很难排查。 - 冗余代码:每个业务方法都要加
if(this.passedCheck)判断,代码重复臃肿。
- 违反单一职责:
结论:方案1明显更优,它的设计更清晰,职责划分明确,也能避免很多潜在bug。
二、用函数/类决定实例化哪个类是良好实践吗?
你举的这个例子其实就是简单工厂模式,这是非常经典且实用的编程实践,完全没问题!
先看你的示例代码:
public Animal decideWhichClass(Status status){ if(status == StatusA){ return new Dog(); } else if(status == StatusB){ return new Cat(); } // 可返回默认实例或抛出异常 return null; } // 调用方代码 Animal a = decideWhichClass(currentStatus);
这种设计的好处非常明显:
- 解耦实例化逻辑和业务代码:调用方不需要知道
Dog、Cat的存在,只需要传入Status就能拿到对应的Animal实例,降低了模块间的耦合度。 - 集中管理实例化规则:后续新增
Bird类时,只需修改decideWhichClass方法,不用改动所有调用处的代码,符合开闭原则(如果分支过多,可进一步优化为注册式工厂,但基础版本已足够好用)。 - 代码更简洁:调用方不用写一堆
if-else判断实例化哪个类,可读性更好。
当然也有需要注意的点:如果判断分支过多,这个工厂函数会变得臃肿,此时可以考虑用反射、策略模式或注册列表来优化,但这都是进阶手段,基础的简单工厂在大多数场景下都非常合适。
内容的提问来源于stack exchange,提问作者Hawii Hawii
相关产品推荐
相关产品推荐

