类层次优先于标签类

public class Figure{
    enum Shape {
        RECTANGLE,
        CIRCLE
    }
     
    // Tag field - the shape of this figure
    final Shape shape;
     
    // These field are use only if shape if RECTANGLE
    double length;
    double width;
     
    // This field is use only if shape is CIRCLE
    double radius;
     
    // Constructor for circle
    public Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }
     
    // Constructor for rectangle
    public 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();
        }
    }
}

这种标签类的缺点

  1. 职责不唯一
  2. 可读性差
  3. 内存占用增加了
  4. 不能将length、width 、radius域设置为final
  5. 不利于扩展

总结就是一句话:标签类过于冗长、容易出错,并且效率低下

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;
    }
}

圆形与长方形的共同点在于都有计算面积的能力。
讲这种共同的能力放在根类Figure中。
如果还存在其他公用的属性,也应该放到该类中。
这种方式即为具有类层次。

类层次还有一个好处即可以反映类型之间本质的层次关系。
假如我们现在要加入一种正方形

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

这种继承也可以反映现实中正方形属于长方形一种。

总而言之,标签类很少有适用的时候。当你想要编写一个包含显示的标签域的类时,应该考虑一下,这个标签是否可以被取消,这个类是否可以用类层次来代替,当你遇到一个包含标签域的现有类时,就要考虑将它重构到一个层次结构中去。

你可能感兴趣的:(类层次优先于标签类)