知识卡片
继承映射器如何支持抽象类的查找:委托而非硬塞接口
内容
不管具体用单表继承、类表继承还是具体表继承,组织这些继承层次映射器的基本结构是一致的:按继承层次组织映射器,每个领域类各有一个映射器负责它的存取;具体子类的映射器(如足球运动员映射器)负责声明查找方法(返回具体类型,避免返回抽象类型逼迫调用方做向下转型),加载/保存方法则由每层映射器各自实现自己特有的部分数据,再逐级调用超类的对应方法,层层叠加拼出完整对象。真正棘手的是如何支持”针对抽象超类本身”的查找(比如查一个”运动员”而不指定具体是哪种)。最初直觉是把这类方法直接塞进超类映射器里,但作者发现这样做很别扭:具体映射器本可以直接继承超类映射器的插入/更新方法,可”运动员映射器”却又必须覆盖这些方法去转而调用某个具体映射器,结果是继承和委托这两种机制搅在一起,逻辑绕得让人头晕。更清爽的方案是把映射器拆成两类:一类是抽象运动员映射器(只负责给具体映射器提供可复用的存取基础行为,自己不对外暴露),另一类是独立的运动员映射器类(专门给”运动员层”的操作提供统一入口,实现查找方法,并覆盖插入/更新方法)——它唯一的职责就是判断这次该由哪个具体映射器来处理,然后把任务转交给它。可迁移启发:当继承体系里”针对基类的统一操作”和”继承来的默认实现”混在同一个类身上、导致继承和委托互相打架、逻辑变得难以理清时,值得考虑把”面向抽象类型的统一入口”拆成一个独立的协调者对象,让它专职做分发和委托,而不是硬把这层职责塞进继承树本身。
参考来源
- 位置:《企业应用架构模式》第二部分"模式"之"第12章 对象-关系结构模式"之"12.10.1 运行机制"(源文件:_epub-src/OEBPS/Text/000141.html)
- 结论依据:原文说明"最初的思想是在超类映射器中放入合适的方法,但事实上这种方法很蹩脚。具体映射器类可以使用抽象映射器的插入和更新方法,而运动员映射器的插入和更新方法却需要覆盖这些方法来调用一个具体映射器。结果是某种泛化和组合的结合……我倾向于把映射器分为两类。抽象运动员映射器……另一个是独立的运动员映射器类……它的全部责任就在于找到应该由哪个具体映射器来处理任务,并且把任务委托给这个具体映射器",直接支撑本卡结论。
- 原始内容:运动员映射器提供了查找方法,并且覆盖了插入和更新方法。它的全部责任就在于找到应该由哪个具体映射器来处理任务,并且把任务委托给这个具体映射器。