如何在OOP中调用嵌套RESTful API接口避免父类过度臃肿?
嵌套REST资源OOP封装的可行方案
以下是三种可以避免父类臃肿的落地方式,可根据实际业务场景选择:
方案1:子资源实例持有父资源ID引用(最常用)
在子资源初始化时直接将所属父资源的ID作为内置属性传入,子资源自身的方法可以直接读取该属性完成接口调用,无需依赖父类提供操作方法。
代码示例:
class Order { id: string amount: number // 新增父资源ID属性 shopId: string constructor(shopId: string, orderData: Partial<Order>) { this.shopId = shopId Object.assign(this, orderData) } delete() { // 直接调用接口,两个参数都已内置 return request.delete(`/shop/${this.shopId}/order/${this.id}`) } } // Shop类加载订单时传入自身ID即可 class Shop { id: string orders: Order[] async loadOrders() { const orderList = await request.get(`/shop/${this.id}/order`) // 实例化Order时统一注入shopId this.orders = orderList.map(item => new Order(this.id, item)) } }
该方案逻辑符合直觉,订单本身就具备「所属店铺ID」这个业务属性,代码复杂度最低,适合嵌套层级少于3层的场景。
方案2:上下文自动注入(适合多层嵌套场景)
如果资源嵌套层级很深(例如 /shop/:shopId/order/:orderId/item/:itemId/log/:logId),每层手动传递父ID会产生大量冗余代码,可以通过上下文容器自动注入父资源ID。
代码示例:
// 全局上下文容器 class ResourceContext { private static context = new Map<string, string>() // 临时绑定上下文执行逻辑 static runWith<T>(context: Record<string, string>, fn: () => T): T { const prevContext = new Map(this.context) Object.entries(context).forEach(([key, value]) => this.context.set(key, value)) const result = fn() this.context = prevContext return result } static get(key: string) { return this.context.get(key) } } // Shop类加载订单时绑定shopId上下文 class Shop { id: string orders: Order[] async loadOrders() { const orderList = await request.get(`/shop/${this.id}/order`) this.orders = ResourceContext.runWith({ shopId: this.id }, () => { return orderList.map(item => new Order(item)) }) } } class Order { id: string amount: number shopId: string constructor(orderData: Partial<Order>) { this.shopId = ResourceContext.get('shopId') Object.assign(this, orderData) } delete() { return request.delete(`/shop/${this.shopId}/order/${this.id}`) } }
该方案可以避免多层嵌套时逐层传递父ID的问题,减少重复代码。
方案3:统一资源路径管理器(适合接口频繁调整场景)
如果业务的接口路径规则经常变动,可以单独抽离公共的路径生成模块,所有资源的路径规则统一维护,避免散落在各个类中难以修改:
const ApiPathBuilder = { shop: (shopId: string) => `/shop/${shopId}`, order: (shopId: string, orderId: string) => `${ApiPathBuilder.shop(shopId)}/order/${orderId}` // 其他资源路径统一在这里维护 }
该方案通常和前两种方案配合使用,方便全局调整接口路径规则。
内容的提问来源于stack exchange,提问作者jm18457
相关产品推荐
相关产品推荐

