如何优化公司字段设置校验的Switch逻辑?策略模式是否适用?
问题背景与优化咨询
业务背景
每家公司可将部分字段设置为非必填、不可见,但仅能操作数据库允许的字段。数据库中存储的通用字段规则如下:
public enum Field { UserEmail, UserIdentifier, UserName } public class GeneralFieldSettings { public Field Field { get; set; } public bool CanSetIfIsRequired { get; set; } public bool CanSetIfVisibleOnWebsite { get; set; } } List<GeneralFieldSettings> generalFieldSettings = new List<GeneralFieldSettings>(); generalFieldSettings.Add(new GeneralFieldSettings { Field = Field.UserEmail, CanSetIfIsRequired = false, CanSetIfVisibleOnWebsite = false }); generalFieldSettings.Add(new GeneralFieldSettings { Field = Field.UserIdentifier, CanSetIfIsRequired = true, CanSetIfVisibleOnWebsite = true }); generalFieldSettings.Add(new GeneralFieldSettings { Field = Field.UserName, CanSetIfIsRequired = true, CanSetIfVisibleOnWebsite = false });
从API获取公司字段设置数据:
public class CompanyFieldSettings { public int CompanyId { get; set; } public Field Field { get; set; } public bool IsRequired { get; set; } public bool IsVisibleOnWebsite { get; set; } } CompanyFieldSettings companyFieldSettings = new CompanyFieldSettings { CompanyId = 1, Field = Field.UserEmail, IsRequired = false, IsVisibleOnWebsite = false };
当前通过Switch语句实现校验逻辑:
switch (companyFieldSettings.Field) { case Field.UserEmail: GeneralFieldSettings generalFieldSetting1 = generalFieldSettings.Single(x => x.Field == Field.UserEmail); if (generalFieldSetting1.CanSetIfIsRequired == false && companyFieldSettings.IsRequired == false) throw new Exception("You can't set this field NOT required"); if (generalFieldSetting1.CanSetIfVisibleOnWebsite == false && companyFieldSettings.IsVisibleOnWebsite == false) throw new Exception("You can't set this field NOT visible on website"); break; case Field.UserIdentifier: GeneralFieldSettings generalFieldSetting2 = generalFieldSettings.Single(x => x.Field == Field.UserIdentifier); if (generalFieldSetting2.CanSetIfIsRequired == false && companyFieldSettings.IsRequired == false) throw new Exception("You can't set this field NOT required"); if (generalFieldSetting2.CanSetIfVisibleOnWebsite == false && companyFieldSettings.IsVisibleOnWebsite == false) throw new Exception("You can't set this field NOT visible on website"); break; case Field.UserName: GeneralFieldSettings generalFieldSetting3 = generalFieldSettings.Single(x => x.Field == Field.UserName); if (generalFieldSetting3.CanSetIfIsRequired == false && companyFieldSettings.IsRequired == false) throw new Exception("You can't set this field NOT required"); if (generalFieldSetting3.CanSetIfVisibleOnWebsite == false && companyFieldSettings.IsVisibleOnWebsite == false) throw new Exception("You can't set this field NOT visible on website"); break; }
咨询问题
能否将该Switch逻辑优化为更优雅的实现?策略模式是否为合适的优化方向?
优化方案与分析
一、立即简化:移除Switch,复用通用逻辑
当前Switch语句存在大量重复代码,完全可以通过字典查找+统一校验逻辑来简化,无需引入复杂模式:
优化步骤:
- 将
generalFieldSettings列表转换为字典,提升字段配置的查找效率(建议在初始化阶段完成,避免重复转换); - 根据当前公司设置的字段,直接匹配对应的通用配置;
- 用统一的逻辑校验必填项和网站可见性规则。
代码实现:
// 初始化时将列表转为字典(全局或单次初始化) var fieldSettingsDict = generalFieldSettings.ToDictionary(x => x.Field); // 获取当前字段的通用配置 if (!fieldSettingsDict.TryGetValue(companyFieldSettings.Field, out var generalSetting)) { throw new Exception("无效的字段配置"); } // 统一校验必填项规则 if (!generalSetting.CanSetIfIsRequired && !companyFieldSettings.IsRequired) { throw new Exception($"无法将字段 {companyFieldSettings.Field} 设置为非必填"); } // 统一校验网站可见性规则 if (!generalSetting.CanSetIfVisibleOnWebsite && !companyFieldSettings.IsVisibleOnWebsite) { throw new Exception($"无法将字段 {companyFieldSettings.Field} 设置为网站不可见"); }
这种方案的优势:
- 消除重复代码,逻辑更清晰;
- 性能更优(字典查找O(1),替代原Single的O(n)遍历);
- 后续新增字段时,只需在
generalFieldSettings中添加配置,无需修改校验逻辑。
二、策略模式的适用性分析
策略模式是合适的优化方向,但仅适用于未来字段校验逻辑会出现差异化的场景:
适用场景:
如果后续不同字段需要添加专属校验规则(比如UserEmail需要额外校验格式、UserIdentifier需要关联其他系统校验等),策略模式可以将每个字段的校验逻辑封装为独立类,符合单一职责原则,便于维护和扩展。
策略模式实现示例:
- 定义校验接口:
public interface IFieldValidator { void Validate(CompanyFieldSettings companySettings, GeneralFieldSettings generalSettings); }
- 为每个字段实现专属校验器:
public class UserEmailValidator : IFieldValidator { public void Validate(CompanyFieldSettings companySettings, GeneralFieldSettings generalSettings) { // 通用规则校验 if (!generalSettings.CanSetIfIsRequired && !companySettings.IsRequired) throw new Exception("无法将UserEmail设置为非必填"); if (!generalSettings.CanSetIfVisibleOnWebsite && !companySettings.IsVisibleOnWebsite) throw new Exception("无法将UserEmail设置为网站不可见"); // 可以添加UserEmail专属校验逻辑 // 例如:if (!IsValidEmail(companySettings.UserEmailValue)) throw new Exception("邮箱格式无效"); } } public class UserIdentifierValidator : IFieldValidator { public void Validate(CompanyFieldSettings companySettings, GeneralFieldSettings generalSettings) { if (!generalSettings.CanSetIfIsRequired && !companySettings.IsRequired) throw new Exception("无法将UserIdentifier设置为非必填"); if (!generalSettings.CanSetIfVisibleOnWebsite && !companySettings.IsVisibleOnWebsite) throw new Exception("无法将UserIdentifier设置为网站不可见"); // 专属逻辑扩展... } }
- 构建校验器字典并执行校验:
// 初始化校验器映射(全局初始化) var validatorDict = new Dictionary<Field, IFieldValidator> { { Field.UserEmail, new UserEmailValidator() }, { Field.UserIdentifier, new UserIdentifierValidator() }, { Field.UserName, new UserNameValidator() } }; // 执行校验 if (!validatorDict.TryGetValue(companyFieldSettings.Field, out var validator)) throw new Exception("无效的字段"); if (!fieldSettingsDict.TryGetValue(companyFieldSettings.Field, out var generalSetting)) throw new Exception("无效的字段配置"); validator.Validate(companyFieldSettings, generalSetting);
注意:
如果当前所有字段的校验逻辑都是统一的(仅校验必填和可见性),策略模式会增加代码复杂度,此时第一种简化方案更合适。
内容的提问来源于stack exchange,提问作者Aleksander Chelpski
相关产品推荐
相关产品推荐

