重构手法——对象结构优化类 | 集成体系重构 | 合并层级结构

简介

"合并层次结构"(Collapse Hierarchy)是一种重构手法,适用于当类层次结构过于复杂,存在一些子类或父类没有足够的存在价值时,通过将它们合并,简化类的结构,提高代码的可维护性和可读性。

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

  • 类层次结构过深:存在过多的类继承层级,导致代码理解和维护困难。
  • 子类或父类功能过少:部分子类或父类只有很少的方法或属性,没有充分体现其存在的意义。

合并层次结构(Collapse Hierarchy)的详细步骤

  1. 识别可合并的类
    • 寻找功能相似的类:在类层次结构中,找到那些功能大部分重叠的子类和父类。
    • 检查类的独特性:确定哪些类的独特功能很少,大部分行为都与其他类重复。
  2. 选择合并方式
    • 向上合并:如果子类的独特功能很少,大部分行为都在父类中,可将子类的独特功能移到父类,然后删除子类。
    • 向下合并:若父类功能较少,而子类有较多共同行为,可将父类的属性和方法移到子类,然后删除父类。
  3. 移动成员
    • 根据选择的合并方式,将需要移动的属性和方法从一个类移动到另一个类。
    • 确保移动后的代码逻辑正确,所有依赖关系都得到妥善处理。
  4. 更新引用
    • 检查代码中所有对被合并类的引用,将其更新为对合并后类的引用。
    • 这包括构造函数调用、方法调用等各种引用。
  5. 测试
    • 编译代码:确保代码编译通过,没有任何语法错误。
    • 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
    • 手动测试:如果有必要,进行手动测试以验证功能的正确性。
  6. 代码审查
    • 同行评审:让同事或其他团队成员审查你的更改,确保代码质量和可维护性得到提升。
    • 文档更新:如果项目有维护文档的习惯,记得更新相关文档,说明合并层次结构的影响。

示例

假设有一个简单的图形绘制类层次结构,如下:

java 复制代码
class Shape {
    protected String color;

    public Shape(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }
}

class Circle extends Shape {
    private double radius;

    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }
}

class Square extends Shape {
    private double sideLength;

    public Square(String color, double sideLength) {
        super(color);
        this.sideLength = sideLength;
    }

    public double getSideLength() {
        return sideLength;
    }
}

在这个例子中,Shape类只有一个color属性和获取color的方法,功能较少。CircleSquare类大部分功能依赖于Shape类,且 Shape类没有太多独特功能。这里可以考虑向上合并。

步骤如下:

  1. 识别可合并的类Shape类功能相对较少,可考虑将其与CircleSquare类合并。

  2. 选择合并方式:向上合并。

  3. 移动成员 :将Shape类的color属性和getColor方法移动到CircleSquare类中。

    java 复制代码
       class Circle {
        private String color;
        private double radius;
    
        public Circle(String color, double radius) {
            this.color = color;
            this.radius = radius;
        }
    
        public String getColor() {
            return color;
        }
    
        public double getRadius() {
            return radius;
        }
    }
    
    class Square {
        private String color;
        private double sideLength;
    
        public Square(String color, double sideLength) {
            this.color = color;
            this.sideLength = sideLength;
        }
    
        public String getColor() {
            return color;
        }
    
        public double getSideLength() {
            return sideLength;
        }
    }
  4. 更新引用 :如果有代码创建Shape对象并使用其属性或方法,需更新为创建CircleSquare对象并使用新的结构。

  5. 测试

    • 编译代码:确保代码编译通过,没有任何语法错误。
    • 运行测试:运行所有相关的单元测试,确保重构操作没有引入新的错误。
  6. 代码审查:让同事审查代码,确保没有引入新的问题。

练习

基础练习题

  1. 简单类层次结构合并

    • 给定以下 Java 代码,Animal类作为父类,DogCat类作为子类,Animal类功能较少。请将Animal类与DogCat类进行合并。

      java 复制代码
            class Animal {
          protected String name;
      
          public Animal(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      }
      
      class Dog extends Animal {
          public Dog(String name) {
              super(name);
          }
      
          public void bark() {
              System.out.println(name + " is barking.");
          }
      }
      
      class Cat extends Animal {
          public Cat(String name) {
              super(name);
          }
      
          public void meow() {
              System.out.println(name + " is meowing.");
          }
      }
  2. 属性和方法移动合并

    • 下面的 Java 代码中,Vehicle类作为父类,CarTruck类作为子类,Vehicle类只有一个speed属性和获取speed的方法。请将 Vehicle类与CarTruck类合并,并合理移动属性和方法。

      java 复制代码
        class Vehicle {
            protected int speed;
      
            public Vehicle(int speed) {
                this.speed = speed;
            }
      
            public int getSpeed() {
                return speed;
            }
        }
      
      class Car extends Vehicle {
          private int numDoors;
      
          public Car(int speed, int numDoors) {
              super(speed);
              this.numDoors = numDoors;
          }
      
          public int getNumDoors() {
              return numDoors;
          }
      }
      
      class Truck extends Vehicle {
          private int loadCapacity;
      
          public Truck(int speed, int loadCapacity) {
              super(speed);
              this.loadCapacity = loadCapacity;
          }
      
          public int getLoadCapacity() {
              return loadCapacity;
          }
      }

进阶练习题

  1. 复杂类层次结构合并与依赖处理

    • 在这段 Java 代码中,Employee类作为父类,ManagerDeveloper类作为子类,Employee类有一些通用方法和属性, ManagerDeveloper类有一些独特方法。但Employee类部分功能与子类重叠较多。请进行合理的合并层次结构重构,并处理好方法之间的依赖关系。

      java 复制代码
        class Employee {
            protected String name;
            protected int salary;
      
            public Employee(String name, int salary) {
                this.name = name;
                this.salary = salary;
            }
      
            public String getName() {
                return name;
            }
      
            public int getSalary() {
                return salary;
            }
      
            public void printDetails() {
                System.out.println("Name: " + name + ", Salary: " + salary);
            }
        }
      
      class Manager extends Employee {
          private int numSubordinates;
      
          public Manager(String name, int salary, int numSubordinates) {
              super(name, salary);
              this.numSubordinates = numSubordinates;
          }
      
          public int getNumSubordinates() {
              return numSubordinates;
          }
      
          public void manageTeam() {
              System.out.println(name + " is managing a team of " + numSubordinates + " subordinates.");
          }
      }
      
      class Developer extends Employee {
          private String programmingLanguage;
      
          public Developer(String name, int salary, String programmingLanguage) {
              super(name, salary);
              this.programmingLanguage = programmingLanguage;
          }
      
          public String getProgrammingLanguage() {
              return programmingLanguage;
          }
      
          public void writeCode() {
              System.out.println(name + " is writing code in " + programmingLanguage + ".");
          }
      }
  2. 合并层次结构与多态处理

    • 给定以下 Java 代码,Shape类作为父类,RectangleTriangle类作为子类,Shape类有一个draw 方法,子类重写了该方法。请进行合并层次结构重构,同时确保多态性仍然能够正确实现。

      java 复制代码
        abstract class Shape {
         public abstract void draw();
      }
      
      class Rectangle extends Shape {
         @Override
         public void draw() {
            System.out.println("Drawing a rectangle.");
         }
      }
      
      class Triangle extends Shape {
         @Override
         public void draw() {
            System.out.println("Drawing a triangle.");
         }
      }

综合拓展练习题

  1. 多模块合并层次结构与代码审查模拟
    • 考虑一个简单的 Java 学校管理系统,有Person类作为父类,StudentTeacherStaff类作为子类。Person 类有一些通用的属性和方法,如nameageprintInfo方法。Student类有studentIdenrollCourse方法,Teacher类有 teacherIdteachCourse方法,Staff类有staffIdperformDuty方法。部分功能在类之间存在重叠。

    • 请对这些类进行 "合并层次结构" 重构,合理简化类的层次结构。

    • 假设你完成了重构,请模拟一份简单的代码审查报告,指出重构后的优点和可能存在的潜在问题。

      java 复制代码
        class Person {
         protected String name;
         protected int age;
      
         public Person(String name, int age) {
            this.name = name;
            this.age = age;
         }
      
         public void printInfo() {
            System.out.println("Name: " + name + ", Age: " + age);
         }
      }
      
      class Student extends Person {
         private int studentId;
      
         public Student(String name, int age, int studentId) {
            super(name, age);
            this.studentId = studentId;
         }
      
         public void enrollCourse(String course) {
            System.out.println(name + " with ID " + studentId + " is enrolling in " + course + ".");
         }
      }
      
      class Teacher extends Person {
         private int teacherId;
      
         public Teacher(String name, int age, int teacherId) {
            super(name, age);
            this.teacherId = teacherId;
         }
      
         public void teachCourse(String course) {
            System.out.println(name + " with ID " + teacherId + " is teaching " + course + ".");
         }
      }
      
      class Staff extends Person {
         private int staffId;
      
         public Staff(String name, int age, int staffId) {
            super(name, age);
            this.staffId = staffId;
         }
      
         public void performDuty(String duty) {
            System.out.println(name + " with ID " + staffId + " is performing " + duty + ".");
         }
      }
相关推荐
why15124 分钟前
6.15 操作系统面试题 锁 内存管理
后端·性能优化
丘山子1 小时前
如何确保 Go 系统在面临超时或客户端主动取消时,能够优雅地释放资源?
后端·面试·go
武子康1 小时前
Java-52 深入浅出 Tomcat SSL工作原理 性能优化 参数配置 JVM优化
java·jvm·后端·servlet·性能优化·tomcat·ssl
OnlyLowG1 小时前
SpringSecurity导致redis压力大问题解决
后端
深栈解码1 小时前
OpenIM 源码深度解析系列(十四):事件增量同步机制解析
后端
想用offer打牌1 小时前
一站式了解CDN😈
后端·架构·cdn
红狐寻道1 小时前
osgEarth初探
c++·后端
海拥2 小时前
Java编程语言:核心特性与应用实践
后端
小王学python2 小时前
Python语法、注释之数据类型
后端·python
磊叔的技术博客2 小时前
LLM 系列(四):神奇的魔法数 27
后端·llm