处理继承关系 旨在优化继承结构,消除冗余,解决继承关系不当或耦合过紧的问题,并利用多态性来简化条件逻辑。
以下是第 12 章所有重构技巧的整理、类型和说明:
技巧(中文/英文) | 核心目标与动机 | 做法概要 | 示例说明 |
函数上移 (Pull Up Method) | 消除子类中的 重复代码,将共同行为从子类移动到超类中,从而简化代码结构,使程序更容易理解。 | 确保待提升的函数在子类中是完全一致的。检查其引用的元素(函数调用、字段)都能从超类中调用到。将函数复制到超类,然后移除子类中的函数。 | 将 Employee 和 Department 子类中都存在的 annualCost 函数,提升到共同的超类 Party 中,以消除重复计算年成本的逻辑。 |
字段上移 (Pull Up Field) | 当子类中存在 重复的字段 或字段对于超类的某个(已提升或待提升的)行为至关重要时,应将其移动到超类中。 | 确保所有引用该字段的函数都已处理(可能已提升)。将字段声明移动到超类,并移除子类中的声明。 | 将 Salesman 和 Engineer 子类中都使用的 name 字段提升到 Employee 超类中,因为 Employee 类中的某些行为(如 annualCost)可能需要用到它。 |
构造函数本体上移 (Pull Up Constructor Body) | 如果子类的构造函数中有 公共代码,应将其移动到超类构造函数中,以避免重复。 | 使用 移动语句 将子类构造函数中的公共语句移动到 super() 调用之后。逐一移除公共代码,并将其引用的变量作为参数传递给超类构造函数。 | 将 Employee 和 Department 构造函数中对 name 字段的初始化逻辑,移动到超类 Party 的构造函数中,并传入 name 参数。 |
函数下移 (Push Down Method) | 如果超类中的某个函数只与一个(或少数几个)子类有关,则应将其搬移到真正关心它的子类中去,以避免 被拒绝的遗赠。 | 将超类中的函数本体复制到每一个需要它的子类中。删除超类中的函数。从不需要它的子类中删除该函数。 | 如果 Employee 超类中的 quota 函数只对 Salesman 子类有意义,则将其下移到 Salesman 中。 |
字段下移 (Push Down Field) | 如果某个字段只被一个子类(或一小部分子类)用到,就将其搬移到需要该字段的子类中,以避免超类承担不必要的责任。 | 在所有需要该字段的子类中声明该字段。将该字段从超类中移除。 | 如果 Employee 超类中的 quota 字段只被 Salesman 子类用到,则将其下移到 Salesman 中。 |
以子类取代类型码 (Replace Type Code with Subclasses) | 当类中包含一个 类型码(type code)字段,且该字段的值决定了程序的不同行为时(重复的 switch),应引入子类和多态来取代条件逻辑。 | 为类型码的每个值创建相应的子类。使用 以工厂函数取代构造函数 来实例化正确的子类。将与类型码相关的条件逻辑通过 以多态取代条件表达式 移动到子类中。 | 将基于员工类型码(如 “engineer”、“manager”)的 switch 逻辑替换为 Engineer、Manager 等子类,用多态处理各自特有的行为。 |
移除子类 (Remove Subclass) | 如果一个子类不再带来足够的结构或价值(冗赘的元素),或者其特有行为已不再重要,就应将其与超类合并。 | 使用 字段上移、字段下移、函数上移 和 函数下移 将所有元素都移到同一个类中。调整所有对子类的引用点,使其引用合并后的类,然后移除子类。 | 如果一个 Salesman 子类与 Employee 超类之间差异不大,则将其合并到 Employee 中。 |
提炼超类 (Extract Superclass) | 当两个或多个类有 共同的行为或数据 时,提炼出一个共同的超类,以消除重复代码。 | 创建一个空的超类,让现有类继承它。使用 字段上移 搬移共同数据,使用 函数上移 搬移共同行为。 | 将 Employee 和 Department 中共同的 name 字段和 annualCost 行为提炼到一个新的 Party 超类中。 |
折叠继承体系 (Collapse Hierarchy) | 如果一个类与其超类 差异不大,不值得再作为独立的类存在,则应将其合并起来。 | 选择合适的类名,将所有元素都移动到选中的类中。调整所有引用点,使其引用合并后留下的类,然后移除目标类。 | 如果 Salesman 子类与 Employee 超类在功能上没有实质区别,则可以将其合并(折叠)。 |
以委托取代子类 (Replace Subclass with Delegate) | 当继承关系 不当 或 过于紧密 (3.23),或者对象需要 动态地改变类型 时,使用委托来取代继承,以降低耦合度。 | 创建一个委托类,它接受指向超类的反向引用以及子类特有的数据。将子类特有的函数和数据搬移到委托类中,并在超类中添加一个委托字段和分发逻辑。 | 将 PremiumBooking 子类替换为一个 PremiumBookingDelegate 对象,该委托对象在 Booking 类内部被引用,以处理高级预订的特有行为,同时允许 Booking 对象动态转换预订类型。 |
以委托取代超类 (Replace Superclass with Delegate) | 当子类继承了超类,但 不需要或不适用 超类的所有函数,或者子类与超类之间的耦合过强时。 | 在子类中新建一个字段引用超类的一个对象(委托对象)。针对超类的每个函数,在子类中创建一个 转发函数,将调用请求转发给委托引用。完成后,移除继承关系。 | Scroll 类不应该继承 CatalogItem(因为卷轴是目录项的实例)。通过创建 Scroll 上的字段引用 CatalogItem 实例,并转发 id、title 等访问,从而消除不当的继承关系。 |
这些技巧的核心在于,通过 上移/下移 (Pull Up/Push Down) 来优化既有层次结构,通过 提炼/折叠 (Extract/Collapse) 来创建或简化层次结构,并通过 多态/委托 (Polymorphism/Delegate) 来处理类型变化和降低类间耦合。
- Author:CoderWdd
- URL:https://www.wuinsights.top//article/02d954f7-78a0-4b73-8801-369226ee5f9b
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts