标签类,这里指类依据本身的某个属性,来确定类会产生不同的对象。很明显,这不符合类的单一职责原则。如:
public class Figure {
enum Shape {
RECTANGLE, CIRCLE
}
private Shape shape;
/** rectangle fields*/
private double length;
private double widht;
/** circle fields*/
private double radius;
/** constructor for circle*/
Figure(int radius) {
this.radius = radius;
}
/** constructor for rectangle*/
Figure(int length, int width) {
this.length = length;
this.widht = width;
}
double area() {
switch (shape) {
case RECTANGLE:
return length * widht;
case CIRCLE:
return Math.PI * radius * radius;
default:
throw new AssertionError();
}
}
}
以上代码表示,类Figure
拥有length
、width
、radis
和shape
属性,且当shape
为RECTANGLE
的时候,只使用length
和width
属性,当shape
为CIRCLE
的时候,则使用radius
属性。这里属性shape
就相当于标签,用于区分类的不同。
由于设计不符合单一职责原则,那我们按如下步骤进行重构:
1. 在标签类中选取依赖于标签的方法,提取作为抽象类的共同方法。这里就是area()
方法。
public abstract class AbstractFigure {
public abstract double area();
}
- 新建继承于抽象类的子类,并将特定标签相关的属性及方法移到该子类中。在这里,比如说当
shape
为CIRCLE
时,特定相关的就是属性radius
及构造方法。
public class CircleFigure extends AbstractFigure {
private double radius;
public CircleFigure(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public class RectangleFigure extends AbstractFigure {
private double length;
private double width;
public RectangleFigure(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}