类层次由于标签类

有时候,可能会遇到带有两种甚至更多种分格的实例的类,并包含标识实例分格的标签域,举个栗子

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

这样的标签类有许多缺点,充斥着样板代码,包括枚举,标签域以及条件语句。由于多个乱七八糟的实现挤在了一个类中,破坏了可读性。一句话总结标签类过于冗长,容易出错,并且效率低下。

好的处理方法——子类化类型

为了将标签类转化成类层次,首先要为标签类中的每个方法都定义一个包含抽象方法的抽象类。在上述类中只有一个这样的方法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;
    }
}

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

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