pecs原则在抽象工厂模式中不直接驱动产品族创建,但通过方法级通配符提升类型安全与复用性:返回集合用? extends product(只读生产者),接收参数用? super config(只写消费者),产品接口方法按需应用pecs,泛型工厂类中pecs作补充而非替代。

PECS 原则在抽象工厂模式中不直接驱动产品族的创建逻辑,但它能显著提升工厂方法签名的类型安全性和复用性——尤其当工厂返回泛型集合、接收泛型参数,或需统一处理不同子类产品时。
工厂方法返回产品集合:用 ? extends Product(Producer 场景)
抽象工厂常提供批量获取某类产品的方法,例如“获取所有水果”或“获取当前配置下的全部UI组件”。此时集合只被读取,属于生产者:
- 声明为 List extends Fruit>,可安全接收
List<apple></apple>、List<banana></banana>或List<fruit></fruit>,调用方统一按Fruit处理 - 禁止向该集合写入(除 null),避免混入不兼容子类(如往
List extends Fruit>中 add(new Car()) 编译失败) - 示例:
public List extends UIComponent> createAllComponents(Theme t)—— 返回按钮、文本框等具体组件,但上层只需遍历渲染
工厂接收配置或上下文参数:用 ? super Config(Consumer 场景)
当工厂需要注入通用配置、策略或元数据时,参数应支持更宽泛的父类型,确保灵活性:
- 声明为 void configure(? super DatabaseConfig config),可传入
MySQLConfig、PostgreSQLConfig或其公共父类DatabaseConfig - 工厂内部可安全调用
config.getTimeout()等父类定义的方法,无需向下转型 - 若用
? extends DatabaseConfig,反而会限制只能传入子类,失去通用性
产品族接口的泛型建模:避免在工厂顶层硬编码通配符
抽象工厂本身通常不带泛型参数(如 interface GUIFactory),但其产品接口可结合 PECS 设计协作契约:
- 按钮接口若需接受事件处理器,用
void setOnClickListener(? super ClickEvent)—— 允许传入ClickEvent或其任意父类型(如Event),增强回调兼容性 - 渲染器接口若输出组件列表,返回
List extends Renderable>—— 调用方无需关心是TextView还是ImageView,统一调用render() - 关键点:通配符放在具体产品接口的方法上,而非工厂类声明,保持工厂轻量且面向契约
与泛型工厂类的协同:优先用类型参数,PECS 作补充
若工厂本身是泛型(如 class GenericFactory<t extends product></t>),PECS 更多用于方法级约束:
- 创建方法:
<u extends t> U create(Class<u> type)</u></u>—— 利用类型推导保证返回子类 - 批量注册方法:
void registerAll(Collection extends T> products)—— 作为消费者接收各种 T 子类实例,内部安全添加到内部集合 - 此时 PECS 不替代泛型参数,而是让方法对入参/出参更宽容,同时守住类型边界
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











