You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化公司字段设置校验的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语句存在大量重复代码,完全可以通过字典查找+统一校验逻辑来简化,无需引入复杂模式:

优化步骤:

  1. 将generalFieldSettings列表转换为字典,提升字段配置的查找效率(建议在初始化阶段完成,避免重复转换);
  2. 根据当前公司设置的字段,直接匹配对应的通用配置;
  3. 用统一的逻辑校验必填项和网站可见性规则。

代码实现:

// 初始化时将列表转为字典(全局或单次初始化)
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需要关联其他系统校验等),策略模式可以将每个字段的校验逻辑封装为独立类,符合单一职责原则,便于维护和扩展。

策略模式实现示例:

  1. 定义校验接口:
public interface IFieldValidator
{
    void Validate(CompanyFieldSettings companySettings, GeneralFieldSettings generalSettings);
}
  1. 为每个字段实现专属校验器:
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设置为网站不可见");
        
        // 专属逻辑扩展...
    }
}
  1. 构建校验器字典并执行校验:
// 初始化校验器映射(全局初始化)
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:25:05