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();
}
}
}
这种标签类的缺点
- 职责不唯一
- 可读性差
- 内存占用增加了
- 不能将length、width 、radius域设置为final
- 不利于扩展
总结就是一句话:标签类过于冗长、容易出错,并且效率低下
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);
}
}
这种继承也可以反映现实中正方形属于长方形一种。
总而言之,标签类很少有适用的时候。当你想要编写一个包含显示的标签域的类时,应该考虑一下,这个标签是否可以被取消,这个类是否可以用类层次来代替,当你遇到一个包含标签域的现有类时,就要考虑将它重构到一个层次结构中去。