能力集合建模指南 能力对象与KeyValue查询模式对比
能力集合建模指南_能力对象与KeyValue查询模式对比
当系统需要表达“设备/平台支持什么”时,常见有两种建模方式:能力对象(Capability Object)与Key-Value 查询(Capability Key)。本文从抽象模型、适用场景、演进路径与混合架构出发,给出可落地的选型建议。
目录
- 问题背景
- 能力语义分层术语表
- 两种主流模型
- 核心差异对照
- 为什么会出现两种模型
- 混合模式才是常态
- 选型决策树
- 演进策略:先 Key 后对象
- Schema 版本治理与兼容规则
- 通用接口草图
- 常见反模式
- 附录:Android / iOS / Web 能力模型映射表
- 免责声明
- 延伸阅读
问题背景
在 Android、iOS、Web 与服务端系统里,“能力集合”通常用于回答三类问题:
- 当前设备/环境支持哪些功能
- 在特定参数组合下是否可配置
- 新增能力后如何保持兼容与可演进
典型实践会落入两条路线:
- 能力对象模型:一次性返回结构化能力描述对象
- Key-Value 查询模型:通过 key 逐项查询是否支持
能力语义分层术语表
为避免“支持但不可用”的误判,建议在设计评审中统一以下术语:
| 术语 | 含义 | 常见来源 | 典型误区 |
|---|---|---|---|
| Declared Capability | 平台/设备声明具备的能力 | HAL、Framework、浏览器接口存在性 | 把“声明支持”当“当前可用” |
| Runtime Availability | 当前运行时是否可用 | 会话状态、资源占用、系统温控、前后台态 | 忽略动态变化导致线上偶发失败 |
| Config Feasibility | 指定参数组合是否可行 | 编码器约束、分辨率×帧率×格式组合 | 仅看单个能力字段做决策 |
| Policy Allowed | 权限/策略层是否允许 | 权限、企业策略、浏览器安全上下文 | 通过能力探测但实际被策略拒绝 |
推荐判定顺序:Declared→Policy→Runtime→Feasibility。
对外 API 可同时返回四层状态,避免业务层自行拼凑。
两种主流模型
1) 能力对象模型(Capability Object Model)
代表思路:返回一个只读能力对象,包含静态规格、范围与约束。
CameraCharacteristics ├─ supportedHardwareLevel ├─ availableFpsRanges ├─ availableFormats └─ ...特点:
- 能力表达结构化、层次化
- 适合“初始化阶段一次决策”
- 对“组合约束”表达更自然(如分辨率 × 帧率 × 编码)
2) Key-Value 查询模型(Capability Key Model)
代表思路:把能力离散化为 key,调用方按需查询。
FEATURE_CAMERA FEATURE_NFC FEATURE_BLUETOOTH_LE特点:
- 扁平、轻量、便于扩展
- 新增能力通常只需新增 key
- 调用方只关心“有/无”时成本最低
核心差异对照
| 维度 | 能力对象模型 | Key-Value 查询模型 |
|---|---|---|
| 表达能力 | 结构化、可表达层级与范围 | 离散化、布尔或简单值 |
| 获取方式 | 一次获取,后续只读 | 按需多次查询 |
| 组合约束 | 强(适合复杂约束) | 弱(需额外规则层) |
| 扩展性 | 改结构可能牵动面大 | 新增 key 通常较平滑 |
| 兼容策略 | 需谨慎处理字段演进 | 天然向前兼容较好 |
| 典型场景 | 硬件规格、驱动能力、编解码参数 | 功能开关、插件特性、平台特征 |
为什么会出现两种模型
能力对象模型常见动因
- 能力彼此关联,不能割裂判断
- 初始化时要做一次完整配置决策
- 业务需要“能力空间全貌”,而非单点特性
Key-Value 模型常见动因
- 能力彼此独立,可离散判断
- 平台长期演进,新增能力频繁
- 调用方只需
isSupported(key)级别答案
混合模式才是常态
现实系统常是“对象 + key”并存:
- 外层对象:承载能力上下文与生命周期
- 内层 key:承载演进与细粒度扩展
渲染错误:Mermaid 渲染失败: Parse error on line 5: ... D --> E[isSupported(key)] -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
这种结构兼顾了:
- 复杂约束表达
- 向前兼容与增量扩展
- API 面稳定性
选型决策树
一句话经验:
- 像“规格表”就用对象
- 像“功能开关列表”就用 key
- 两者都需要时,用混合模型
演进策略:先 Key 后对象
很多系统的可控路径是:
- 早期:能力少,先用 Key-Value 低成本起步
- 中期:能力增多,出现范围/组合约束
- 后期:引入能力对象做快照,并保留 key 体系
| 阶段 | 推荐模型 | 目标 |
|---|---|---|
| 初期 | Key-Value | 快速落地、低耦合 |
| 成长期 | Key + 规则层 | 承载组合限制 |
| 稳定期 | 对象快照 + Key 扩展 | 兼顾表达力与演进 |
Schema 版本治理与兼容规则
能力协议长期运行时,建议把版本治理写成“硬规则”:
| 变更类型 | 兼容级别 | 推荐策略 |
|---|---|---|
| 新增可选字段/新 key | 向前兼容 | 允许旧客户端忽略;默认值语义必须明确 |
| 字段语义变更 | 破坏性高 | 禁止原地改语义;新增字段并标记旧字段 deprecated |
| 字段删除 | 破坏性高 | 至少经历 2 个版本窗口:标记弃用 → 删除 |
| 类型变更(int→string) | 破坏性高 | 新字段承载新类型,旧字段保留兼容读取 |
发布建议:
- 双读期:新旧字段并存,服务端/SDK 同时支持。
- 双写期:若有回传链路,写新字段同时回填旧字段。
- 观测闸门:按版本统计字段命中率,达到阈值再下线旧字段。
- 失败回退:
schemaVersion不可识别时降级到最小能力集,而非直接崩溃。
通用接口草图
// 能力 key 查询(演进友好)interfaceCapabilityQuery{isSupported(key:string):boolean;getInt?(key:string):number|undefined;getRange?(key:string):[number,number]|undefined;}// 能力对象快照(配置决策友好)interfaceCapabilitySnapshot{version:string;constraints:Record<string,unknown>;features:Record<string,unknown>;}落地建议:
- 对外 API 保持稳定(查询接口与对象字段分层)
- 对内统一能力注册表,避免多处重复定义 key
- 对“组合可行性”提供显式校验函数,避免业务层拼凑判断
常见反模式
| 反模式 | 风险 | 修正方式 |
|---|---|---|
| 全部能力都塞进一个超大对象 | 字段膨胀、兼容困难 | 按域拆分对象,保留 key 扩展 |
| 全部能力都做布尔 key | 无法表达范围与约束 | 引入范围型/结构化字段 |
| 业务层自行拼能力规则 | 规则散落、结果不一致 | 下沉到统一可行性判定层 |
| 无版本语义 | 线上升级行为不可预测 | 增加 capability schema/version |
附录:Android / iOS / Web 能力模型映射表
| 平台 | 典型 API | 偏对象模型 | 偏 Key/查询模型 | 建模建议 |
|---|---|---|---|---|
| Android | Camera2 / PackageManager | CameraCharacteristics(含范围、枚举、组合约束) | PackageManager.hasSystemFeature(...)、feature string/version 查询 | 硬件链路用对象快照;系统特性与可选模块用 feature key |
| iOS | AVFoundation / 运行时能力判断 | AVCaptureDevice、formats/ranges 等结构化能力 | 通过 selector、availability、is*Supported类方法做离散判断 | 媒体能力用对象+格式集;系统版本差异通过 availability/feature flag 补充 |
| Web | Navigator / Media / Permissions | MediaCapabilities、MediaTrackCapabilities等对象化结果 | 'serviceWorker' in navigator、CSS.supports(...)、权限/接口探测 | 浏览器差异大,优先 feature detection;需要参数可行性时再引入对象能力探测 |
| 跨端 SDK | 自研抽象层 | CapabilitySnapshot(一次拉取,带版本) | isSupported(key)(轻量判定) | 对外暴露双层 API:对象用于配置决策,key 用于快速守卫 |
映射后的统一实践
- 初始化阶段:拉取一次对象快照并缓存(可带版本/时间戳)。
- 业务分支阶段:用
isSupported(key)做快速路径守卫。 - 复杂组合阶段:走
validate(config, snapshot)做可行性校验。 - 跨端一致性:维护一份平台无关 key 字典与字段映射表,避免业务层直接耦合平台原生命名。
免责声明
- 不同平台 API 的命名、生命周期和线程模型差异较大;本文给出的是建模方法论而非单平台手册。
- 能力数据若来自底层固件/驱动,实际可用性仍需运行时校验与错误回退。
延伸阅读
- Android Developers: Camera2 API (
CameraCharacteristics) - Android Developers: PackageManager features
- Apple Developer Documentation: AVFoundation
- MDN Web Docs: Feature detection
