第20条:类层次优先于标签类

标签类值带有两种甚至多种风格的实例的类,如一个表示圆或者矩形的类:

class Figure {
    enum Shape { RECTANGLE, CIRCLE };
    final Shape shape;
    double length;
    double width;
    double radius;
    
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }

    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }
    
    double area() {
        switch(shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * radius * radius;
            default:
                throw new AssertionError();
        }
    }
}

这种标签类过于冗长,容易出错,并且效率低下。

在Figure类中,只有area方法是矩形或者圆都有的,将它放在类层次的根。

abstract class Figure {
    abstract double area();
}

class Circle extends Figure {
    final double radius;
    Circle(double radius) {
        this.radius = radius;
    }
    double area() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Figure {
    final double length;
    final double width;
    Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    double area() {
        return length * width;
    }
}

类层次可以反映正方形是一种特殊的矩形:

class Square extends Rectangle {
    square(double side) {
        super(side, side);
    }
}

上述的域是被直接访问的,而不是通过访问方法,应该使用访问方法。

标签类很少适用的时候,当想要编写一个包含显式标签域的类时,考虑能否用类层次代替,当遇到一个包含标签域的现有类时,考虑将它重构到一个层次结构中。

原文地址:https://www.cnblogs.com/13jhzeng/p/5709127.html