重构手法——函数行为重塑类 | 语意 | 用委托替换继承

42 阅读2分钟

简介

"用委托替换继承"是解除类耦合的重要重构手法。通过将继承关系改为委托关系,可以消除不必要的"is-a"关系,提高代码灵活性并支持更合理的对象组合。

针对的症状(代码坏味道)

  • 子类仅使用父类的部分功能
  • 需要复用多个不同类的功能
  • 存在违反里氏替换原则的情况
  • 父类方法不适合子类需求

用委托替换继承的详细步骤

  1. 创建委托字段
    • 在子类中添加父类类型的字段
    • 初始化委托对象实例
  2. 建立委托方法
    • 为需要的方法创建转发方法
    • 将super调用改为委托对象调用
  3. 移除继承关系
    • 删除extends声明
    • 处理构造方法初始化
  4. 清理残留方法
    • 重写不需要的父类方法
    • 添加缺失的必要方法

示例

重构前代码:

class MyStack<E> extends Vector<E> {
    public void push(E element) {
        addElement(element);
    }

    public E pop() {
        E obj = peek();
        removeElementAt(size() - 1);
        return obj;
    }
}

重构后代码:

class MyStack<E> {
    private Vector<E> elements = new Vector<>();

    public void push(E element) {
        elements.addElement(element);
    }

    public E pop() {
        E obj = peek();
        elements.removeElementAt(elements.size() - 1);
        return obj;
    }

    public E peek() {
        return elements.lastElement();
    }

    public int size() {
        return elements.size();
    }
}

练习

基础练习题

  1. 简单继承替换

    // 重构前
    class AuditLogger extends FileWriter {
        void logAction(String action) {
            write("ACTION: " + action);
        }
    }
    

进阶练习题

  1. 多方法委托

    // 重构前
    class CachedEmployee extends Employee {
        // 需要缓存功能
    }
    

综合拓展练习题

  1. 多重委托

    // 重构前
    class HybridDataSource extends DatabaseDataSource {
        // 需要文件和数据源功能
    }
    

代码审查要点

  1. 优点:

    • 解除不必要的耦合
    • 精确控制暴露接口
    • 支持动态组合功能
  2. 潜在问题:

    • 保持委托方法一致性
    • 注意对象生命周期管理
    • 避免过度委托导致复杂度