如何在JSON Schema验证器代码中应用开闭原则?
重构JSON Schema验证器以遵循开闭原则
问题分析
你当前的代码存在两个核心问题,直接违反开闭原则:
- 每次新增一个
topic,都要修改IsValidJson里的switch分支,还要修改RestoreJsonSchemas的加载逻辑,对修改开放,不符合开闭原则的要求 JsonSchemaValidator类同时承担了schema加载、验证逻辑分发、具体验证三个职责,违反单一职责原则
下面给出基于策略模式+接口抽象的重构方案,完美契合开闭原则,同时让代码更易扩展和维护。
重构步骤
1. 抽象验证器接口
把每个topic对应的schema加载和验证逻辑抽象成统一接口,让所有具体验证器遵循相同契约:
public interface IJsonSchemaValidator { // 对应topic标识 string Topic { get; } // 加载schema的方法 void LoadSchema(); // 验证JSON的方法 bool Validate(string json); }
2. 实现具体验证器类
针对每个topic单独创建验证器类,把该topic的schema路径、加载逻辑、验证逻辑完全封装进去。比如connection对应的验证器:
public class ConnectionJsonValidator : IJsonSchemaValidator { private const string _schemaPath = "JsonSchemas\\schemaConnection.txt"; private JSchema _schema; public string Topic => "connection"; public void LoadSchema() { try { var schemaContent = File.ReadAllText(_schemaPath); _schema = JSchema.Parse(schemaContent); } catch (Exception ex) { // 可添加日志记录,或根据业务需求处理异常 throw; } } public bool Validate(string json) { if (string.IsNullOrWhiteSpace(json)) return false; try { var jsonObj = JObject.Parse(json); return jsonObj.IsValid(_schema); } catch { // 处理JSON解析或验证错误 return false; } } }
以后新增topic,只需要新建一个实现IJsonSchemaValidator的类,完全不用修改现有代码。
3. 实现验证器管理器
创建管理器类,负责管理所有验证器、批量加载schema、分发验证请求:
public class JsonSchemaValidationManager { private readonly Dictionary<string, IJsonSchemaValidator> _validators = new(); // 构造函数注入所有验证器,便于扩展 public JsonSchemaValidationManager(IEnumerable<IJsonSchemaValidator> validators) { foreach (var validator in validators) { _validators.Add(validator.Topic, validator); } } public void RestoreAllSchemas() { foreach (var validator in _validators.Values) { validator.LoadSchema(); } Console.WriteLine("Restored all JSON schemas."); } public bool IsValidJson(string topic, string json) { if (string.IsNullOrWhiteSpace(topic) || string.IsNullOrWhiteSpace(json)) return false; if (_validators.TryGetValue(topic, out var validator)) { return validator.Validate(json); } // 未知topic的处理逻辑,比如返回false或抛出异常 return false; } }
4. 使用方式
在应用初始化时,注册所有验证器(可手动注册,也可用依赖注入框架自动扫描):
// 手动注册示例 var validators = new List<IJsonSchemaValidator> { new ConnectionJsonValidator(), // 新增其他验证器直接加在这里即可,比如new UserJsonValidator() }; var validationManager = new JsonSchemaValidationManager(validators); validationManager.RestoreAllSchemas(); // 验证调用 bool isConnectionValid = validationManager.IsValidJson("connection", "{\"name\":\"test\"}");
为什么符合开闭原则?
- 对扩展开放:新增任何
topic,只需要新增一个实现IJsonSchemaValidator的类,不需要修改现有代码 - 对修改关闭:现有验证器和管理器的代码无需改动,避免引入新bug
- 同时拆分了职责,每个类只做一件事,代码可读性和可维护性大幅提升
可选优化
- 用依赖注入框架(比如Microsoft DI)自动扫描所有
IJsonSchemaValidator实现类,省去手动注册的麻烦 - 添加schema缓存逻辑,避免重复加载文件
- 统一异常处理和日志记录,方便排查问题
内容的提问来源于stack exchange,提问作者fuba
相关产品推荐
相关产品推荐

