pecs原则在责任链模式中通过? extends t和? super t精准约束数据传递的类型安全边界:前者保障下游安全读取统一语义,后者支持上游灵活注入子类型,避免强转与classcastexception。

PECS 原则在责任链模式中不直接定义链结构,而是精准约束链上各环节间**数据传递的类型安全边界**——当请求或上下文对象沿责任链流动时,用 ? extends T 保证下游能安全读取统一语义,用 ? super T 保证上游可灵活注入子类型,避免强转、擦除或运行时 ClassCastException。
责任链中“请求”作为生产者:用 ? extends Request
当链中某个处理器仅需读取请求内容(如校验字段、提取元数据),且不修改原始请求对象时,应将参数声明为 handle(Request req) 或更安全地使用通配符:
- 若方法接收一个请求集合(例如批量审批请求),应声明为
void processAll(List extends ApprovalRequest> requests) - 这样可接受
List<purchaserequest></purchaserequest>、List<refundrequest></refundrequest>(只要它们继承自ApprovalRequest) - 编译器确保
requests.get(0).getAmount()可调用(因上界明确),但禁止requests.add(...)(防止混入非子类型)
责任链中“上下文”作为消费者:用 ? super Context
当处理器需向共享上下文写入中间结果(如添加日志标记、设置状态码),而该上下文可能被多级处理器复用时,应声明为:
-
void enrich(Context ctx)不够灵活;改用void enrich(Collection super AuditContext> contextSink) - 这样可传入
ArrayList<auditcontext></auditcontext>、LinkedList<processingcontext></processingcontext>(若ProcessingContext是AuditContext的父类)或ArrayList<object></object> -
contextSink.add(new AuditContext("validated"))总是安全;但取出时只能当Object处理,这是边界诚实性的体现
链式调用中的类型管道:copy / filter / map 场景复用
责任链常伴随数据加工(如过滤敏感字段、映射为审计事件),此时 PECS 成为通用操作的骨架:
- 定义工具方法:
public static <t> void filter(List extends T> src, Predicate<t> p, List super T> dest)</t></t> - 调用示例:
filter(pendingOrders, o -> o.isHighValue(), approvedList),其中pendingOrders是List<order></order>,approvedList是List<businessevent></businessevent>(Order extends BusinessEvent) - 编译器全程校验继承关系,无需
(BusinessEvent) o强转,也不依赖List<object></object>中转
与责任链核心组件的协同要点
PECS 不改变 Handler 接口定义本身,但显著提升其泛型参数设计质量:
- 抽象处理器中,避免裸
Object或Request—— 改用<r extends request> void handle(R req)</r>或参数化通配符 - 具体处理器实现时,若只读不写请求,方法签名优先选
boolean validate(List extends ApiRequest>) - 链构建器(如
ChainBuilder.add(handler))内部若缓存处理器列表,其字段应为List<handler super request>></handler>,以容纳不同泛型特化的处理器
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











