重构第八章:重新组织数据

发布时间:2023年12月20日

在这一章作者详细的介绍了一系列的重构手法,旨在优化代码中的数据组织方式,以提高代码的清晰度、可读性和可维护性。这是第八章中列举的一些重新组织数据的重构手法:

自封装字段(Self Encapsulate Field): 如果直接访问字段而不通过访问器方法,可以创建访问器方法,逐步替换对字段的直接访问。
// Before
public class MyClass {
    public int myField;

    // ...

    public void someMethod() {
        int value = myField;
        // do something with value
    }
}

// After
public class MyClass {
    private int myField;

    public int getMyField() {
        return myField;
    }

    // ...

    public void someMethod() {
        int value = getMyField();
        // do something with value
    }
}

通过将字段封装在访问器方法中,我们提高了对字段的控制,并使得以后更容易修改其行为。

以对象取代数据值(Replace Data Value with Object): 使用多个字段表示某个概念时,可以将这个概念封装为一个对象。

// Before
public class Point {
    public int x;
    public int y;

    // ...

    public void moveTo(int newX, int newY) {
        x = newX;
        y = newY;
    }
}

// After
public class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void moveTo(int newX, int newY) {
        // logic for moving to new coordinates
    }
}

通过引入一个 Point 类,我们将点的概念更好地封装,使得代码更具表达力。

以值对象取代引用对象(Replace Reference with Value): 当对象的身份不重要,只关心其值时,将对象改为不可变的值对象,以便通过值比较进行比较。

// Before
public class Currency {
    private String code;

    public Currency(String code) {
        this.code = code;
    }

    // ...

    public boolean equals(Currency other) {
        return this.code.equals(other.code);
    }
}

// After
public class Currency {
    private String code;

    public Currency(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

    // ...
}

通过将 Currency 类改为不可变的值对象,我们简化了对比逻辑,提高了可读性。

以子类取代类型码(Replace Type Code with Subclasses): 使用类型码来表示不同的类型时,为每个类型创建一个子类,以便通过多态来替代类型码。

// Before
public class Animal {
    private int type;
    public static final int DOG = 1;
    public static final int CAT = 2;

    // ...

    public void makeSound() {
        if (type == DOG) {
            // dog sound
        } else if (type == CAT) {
            // cat sound
        }
    }
}

// After
public abstract class Animal {
    // ...

    public abstract void makeSound();
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        // dog sound
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        // cat sound
    }
}

通过创建子类,我们使用了多态来代替类型码,使得代码更加灵活和可扩展。

引入外加数据(Introduce Foreign Data): 当需要在其他类中添加一些数据而不是在本地类中添加时,在本地类中创建一个字段,并通过方法在其他类中传递数据。

// Before
public class Order {
    // ...

    public double calculateTotalPrice(Customer customer) {
        // use customer data for calculation
    }
}

public class Customer {
    // ...
}

// After
public class Order {
    private Customer customer;

    public double calculateTotalPrice() {
        // use this.customer data for calculation
    }
}

public class Customer {
    // ...
}

通过引入外加数据,我们将数据传递逻辑更清晰地放置在了 Order 类中。

移除标志字段(Remove Flag Argument): 函数中使用标志字段来决定其行为时,将标志字段拆分为多个明确的参数,使得函数的行为更清晰。

// Before
public class Printer {
    // ...

    public void printDocument(String document, boolean isColor) {
        if (isColor) {
            // print color document
        } else {
            // print black and white document
        }
    }
}

// After
public class Printer {
    // ...

    public void printColorDocument(String document) {
        // print color document
    }

    public void printBlackAndWhiteDocument(String document) {
        // print black and white document
    }
}

通过拆分标志字段,我们使函数的行为更加明确,提高了可读性。

以对象取代数组(Replace Array with Object): 使用数组表示一组相关的数据时,创建一个对象,将数组替换为对象的字段,使得数据更易于扩展和维护。

// Before
public class Team {
    public String[] members;

    // ...
}

// After
public class Team {
    private List<String> members;

    public Team(List<String> members) {
        this.members = members;
    }

    // ...
}

通过引入对象,我们提高了对团队成员的控制,并使得相关数据更易于扩展。

以数据类取代记录(Replace Record with Data Class): 使用一组字段表示记录时,将字段封装为一个数据类,以提高代码的表达力。

// Before
public class Person {
    public String name;
    public int age;

    // ...
}

// After
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // ...
}

通过引入数据类,我们使人物信息更清晰地封装,提高了代码的表达力。

以多态取代条件表达式(Replace Conditional with Polymorphism): 使用条件表达式来选择不同的行为时,使用多态将条件表达式替换为具体的子类,以实现更清晰的逻辑。

// Before
public abstract class Shape {
    // ...

    public void draw() {
        if (this instanceof Circle) {
            // draw circle
        } else if (this instanceof Square) {
            // draw square
        }
    }
}

// After
public interface Shape {
    void draw();
}

public class Circle implements Shape {
    // draw circle
}

public class Square implements Shape {
    // draw square
}

通过使用多态,我们消除了条件表达式,使得代码更加简洁和易于扩展。

以观察者取代数据(Replace Data Value with Observer): 一个数据的变化需要通知其他地方,但使用了回调函数时,使用观察者模式将数据的变化通知到观察者。

// Before
public class Data {
    private int value;
    private List<Callback> callbacks;

    // ...

    public void setValue(int newValue) {
        this.value = newValue;
        notifyCallbacks();
    }

    private void notifyCallbacks() {
        for (Callback callback : callbacks) {
            callback.onValueChanged(value);
        }
    }
}

// After
public class Data extends Observable {
    private int value;

    // ...

    public void setValue(int newValue) {
        this.value = newValue;
        setChanged();
        notifyObservers(value);
    }
}
通过引入观察者模式,我们使得数据变化通知更具扩展性,符合面向对象设计原则。

这些重新组织数据的重构手法有助于提高代码的清晰度、可读性和可维护性,同时使数据的组织方式更加合理。在应用这些手法时,需要仔细考虑系统的整体结构和需求,选择合适的手法进行优化。就像整理家里物品一样,通过精心的整理,让代码更加井然有序,易于管理和维护。

文章来源:https://blog.csdn.net/qq_44444470/article/details/134810836
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。