是不是所有 polymorphic 的场景,都可以用这种模式?

学习 rails delegated_type 的疑问

并不是所有的 polymorphic 场景都适合用 delegated_type 来实现。delegated_type 是专门用于一种特殊的多态关系——“代表类型”(Delegate Type)模式。它能够在某些情况下替代多态关联,但它的适用场景有限,并不能完全取代传统的 polymorphic 关联。

适合 delegated_typepolymorphic 场景

delegated_type 适用于以下 polymorphic 场景:

  1. 代理单一属主:例如 Comment 属于 ArticlePhoto,但不会同时属于多个对象。这种情况下,delegated_type 可以将一个代表对象(如 Comment)代理到指定的对象(如 ArticlePhoto)。

  2. 关系类型数量有限且稳定:如果一个多态关联的类型集是有限的、且不会频繁变化(比如 MessageNotificationFriendRequestNotificationCommentNotification),delegated_type 可以很方便地实现这种有限的多态逻辑。

  3. 自动处理和代理到单一类型:当需要代表对象代理到特定对象,并希望通过代理对象调用实际对象的方法时,delegated_type 提供了一个简化的方式。使用 comment.commentable 就能直接获得 ArticlePhoto,而无需额外判断。

不适合 delegated_typepolymorphic 场景

对于以下 polymorphic 场景,delegated_type 并不合适,传统的 polymorphic 关联更加灵活:

  1. 多对多多态关系:如果是需要多对多的多态关系,例如标签系统(Tag 可以属于多个 ArticlePhoto 等),delegated_type 无法支持这种多对多的多态需求。需要用传统的 polymorphic 结合连接表来实现。

  2. 频繁扩展的类型集合:当多态类型集合频繁变动时(例如,如果 commentable 的对象类型很多或未来可能增加新的类型),delegated_type 会显得僵硬。因为 delegated_type 要求在代码中明确指定类型列表。

  3. 通用多态接口:如果希望所有多态对象都能实现通用的接口,而不是依赖具体的类型集合(例如,Imageable 可以应用于任何对象类型,不仅仅是 ArticlePhoto),传统的 polymorphic 关联更加灵活。这样即使增加新的关联类型,也无需修改现有模型。

  4. 复杂的继承关系:如果涉及复杂的继承关系,比如不同的子类需要不同的逻辑处理(如 Notification 可能有不同子类,各自的关联和逻辑也不同),传统的 polymorphic 实现比 delegated_type 更具扩展性。

delegated_typepolymorphic 的区别

| 特性 | delegated_type | polymorphic |
|--------------------------|------------------------------------------------------|------------------------------------------|
| 适用关系 | 一对多多态关系 | 一对多和多对多多态关系 |
| 关系的类型集 | 固定、有限、稳定的类型集 | 灵活、可以随时扩展 |
| 使用场景 | 代理单一属主类型,简化多态逻辑 | 多态关联较多、类型集多样的关系 |
| 维护成本 | 当新增类型时需修改代码 | 扩展性强,不需修改代码 |

总结

delegated_type 是一种非常有用的工具,但适用范围有限。它在特定的多态场景中比 polymorphic 更简洁,但无法完全取代 polymorphic。如果是复杂或灵活需求较高的多态场景,传统的 polymorphic 关联依然更合适。