从其他对象创建新对象时instanceOf的问题

时间:2013-05-24 16:40:45

标签: java if-statement factory instanceof downcast

我有一个类负责从Formation个对象创建Shape个对象。形状正如名称所示,在画布上绘制的形状(TriangleShapeRectangleShape等等。)

形式类似于形状,但我打算以不同的方式使用它们。

例如,RectangleShape看起来像这样:

public class RectangleShape extends Shape {

public RectangleShape() {
    this(0, 0, 0, 0);
}

public RectangleShape(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;

    this.nPoints = 4;
}

@Override
public void drawShape(Graphics2D g) {
    Color color = g.getColor();
    fillShape(g, new Color(g.getColor().getRed(), g.getColor().getGreen(), g.getColor().getBlue(), 16));
    g.setColor(color);

    g.drawLine(x, y, x + width, y);
    g.drawLine(x, y, x, y + height);
    g.drawLine(x, y + height, x + width, y + height);
    g.drawLine(x + width, y, x + width, y + height);
}

@Override
public String toString() {
    return "Rectangle";
}

@Override
public Shape createCopy() {
    return new RectangleShape();
}

@Override
public void fillShape(Graphics2D g) {
    xPoints = new int[] {
        x,
        x,
        x + width,
        x + width
    };

    yPoints = new int[] {
        y,
        y + height,
        y + height,
        y
    };

    g.fillPolygon(xPoints, yPoints, nPoints);
}
}

我保留一份声明为List<Shape> = new ArrayList<>();的所有绘制形状的列表。

当我需要从形状动态创建阵型时,我的问题就出现了。 第一种方法是使用这样的方法:

public static TriangleFormation createFormationFrom(TriangleShape shape) {
    // my code here
}

public static RectangleFormation createFormationFrom(RectangleShape shape) {
    // my code here
}

public static PentagonFormation createFormationFrom(PentagonShape shape) {
    // my code here
}

public static HexagonFormation createFormationFrom(HexagonShape shape) {
    // my code here
}

public static OvalFormation createFormationFrom(OvalShape shape) {
    // my code here
}

问题是,当我从列表中检索形状时,它的类型为Shape,如果不将形状转换为适当的类,我就不能调用任何这些方法,这就引出了使用问题instanceOf运营商。

我是否应该在一个类中合并Shape和Formation,我是否应该尝试实现一个Visitor模式(如果是这样,在这种情况下会怎样做)或者还有其他我没想过的东西?

1 个答案:

答案 0 :(得分:1)

这完全取决于您希望ShapeFormation分开的程度。最简单的解决方案是 - 如您所述 - 将Formation createFormation()方法添加到Shape接口。

但如果你想让ShapeFormation分开,你就必须做更先进的事情。我建议不要使用访问者模式,因为它非常不灵活。

作为替代方案,请考虑添加FormationBuilder类:

public interface FormationBuilder
{
    /**
     * Builds a particular Formation implementation from the given shape.
     * Perhaps the shape is passed into the constructor of the Formation,
     * perhaps this method extracts the necessary information to build the
     * Formation...
     */
    Formation build(Shape shape);
}

这可以用于这样的工厂:

public class FormationFactory
{
    private final Map<Class<? extends Shape>, FormationBuilder> builders
            = new HashMap<Class<? extends Shape>, FormationBuilder>();

    public <T extends Shape> void register(
            Class<T> shapeType, FormationBuilder builder);
    {
        builders.put(shapeType, builder);
    }

    public Formation getFormation(Shape shape)
    {
        return builders.get(shape.getClass()).build(shape);
    }
}

但现在的问题是,Factory应该在哪里初始化。这是否符合您的需求取决于您的代码的结构。