带中间工厂的嵌套装饰者模式实现问询:基于IRetrieve接口的三层结构
使用装饰者模式实现IRetrieve接口的三层增强结构
咱们来拆解一下这个用装饰者模式搭建的IRetrieve接口三层结构,这种设计能给核心检索功能灵活加上分批、超时控制的增强,非常实用:
首先是基础接口的定义,所有类都要实现这个接口:
public interface IRetrieve { List<Widget> Retrieve(List<long> ids); }
接下来是三个关键类,按照装饰者模式的层级来组织:
核心实现类:RetrieveCore
这是整个装饰链的底层核心,负责执行真正的检索操作,比如从数据库或者外部API获取Widget数据:
public class RetrieveCore : IRetrieve { public List<Widget> Retrieve(List<long> ids) { // 这里写实际的业务逻辑,比如: // return WidgetRepository.GetByIds(ids); } }
超时控制装饰者:RetrieveTimer
作为装饰者,它会包裹下一层的IRetrieve实现,确保检索操作在指定时间内完成,超时就抛出异常或者返回默认结果:
public class RetrieveTimer : IRetrieve { private readonly IRetrieve _innerRetriever; private readonly TimeSpan _timeout; public RetrieveTimer(IRetrieve innerRetriever, TimeSpan timeout) { _innerRetriever = innerRetriever; _timeout = timeout; } public List<Widget> Retrieve(List<long> ids) { // 用Task实现超时控制逻辑 var retrieveTask = Task.Run(() => _innerRetriever.Retrieve(ids)); if (retrieveTask.Wait(_timeout)) { return retrieveTask.Result; } else { throw new TimeoutException($"检索操作超时,已超过{_timeout.TotalMilliseconds}毫秒"); // 也可以根据业务需求返回空列表:return new List<Widget>(); } } }
分批处理装饰者:RetrieveBatcher
这个装饰者会把大的ID列表拆分成小批次,分多次调用下一层的Retrieve方法,最后合并结果,避免单次请求量过大导致的性能问题:
public class RetrieveBatcher : IRetrieve { private readonly IRetrieve _innerRetriever; private readonly int _batchSize; public RetrieveBatcher(IRetrieve innerRetriever, int batchSize) { _innerRetriever = innerRetriever; _batchSize = batchSize; } public List<Widget> Retrieve(List<long> ids) { var finalResult = new List<Widget>(); // 拆分ID列表为多个小批次 for (int i = 0; i < ids.Count; i += _batchSize) { var currentBatch = ids.Skip(i).Take(_batchSize).ToList(); var batchResult = _innerRetriever.Retrieve(currentBatch); finalResult.AddRange(batchResult); } return finalResult; } }
运行时代码示例
咱们可以像这样组装装饰链,按需组合增强功能(顺序可以根据需求调整,比如如果想先超时再分批也可以):
// 从核心开始,逐层包裹装饰者 var coreRetriever = new RetrieveCore(); // 给核心加上超时控制(5秒超时) var timedRetriever = new RetrieveTimer(coreRetriever, TimeSpan.FromSeconds(5)); // 再给超时控制的检索器加上分批处理(每批50个ID) var finalRetriever = new RetrieveBatcher(timedRetriever, 50); // 使用最终的增强版检索器 var targetIds = Enumerable.Range(1, 200).Select(x => (long)x).ToList(); List<Widget> resultWidgets = finalRetriever.Retrieve(targetIds);
内容的提问来源于stack exchange,提问作者Marty
相关产品推荐
相关产品推荐

