Java 从其他对象创建新对象时instanceOf出现问题

Java 从其他对象创建新对象时instanceOf出现问题,java,if-statement,factory,instanceof,downcast,Java,If Statement,Factory,Instanceof,Downcast,我有一个类负责从Shape对象创建Formation对象。形状就是名字所说的,在画布上绘制的形状(TriangleShape,RectangleShape等等) 队形与形状相似,但我计划以不同的方式使用它们 例如,矩形形状,如下所示: public class RectangleShape extends Shape { public RectangleShape() { this(0, 0, 0, 0); } public RectangleShape(int x, int y,

我有一个类负责从
Shape
对象创建
Formation
对象。形状就是名字所说的,在画布上绘制的形状(
TriangleShape
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);
}
}
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
}
我保存了一个所有绘制形状的列表,声明为
list=newarraylist()

当我需要从一个形状动态创建一个队形时,我的问题就来了。 第一种方法是使用如下方法创建一个类:

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

但是如果你想把
形状
s和
队形
s分开,你必须做一些更高级的事情。我建议不要使用访问者模式,因为它非常不灵活

作为另一种选择,考虑添加<代码> FraseBuudiue/Cuff>类:

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);
    }
}
公共类格式化工厂
{

private final MapI不明白你为什么不想向下转换?这能解决问题吗?只需先进行instanceof test以检查它是否是正确的实例类型。使用泛型Formation类怎么样?当然,如果每个Formation根本不同,这可能不起作用。向下转换是一个丑陋且难以扩展的解决方案。访问或者,如果你不会得到太多的形状,也不想支持未知的形状,或者说插件提供额外的形状,那就更有意义了。它甚至比你想把你的类放入到你的类中更像是创建弹出菜单。另一种方法是在每个形状上都有一个toFormation()方法即使我不介意专注于寻找最干净的解决方案,我想我还是会选择
toFormation()
approach.Ty,感谢您的努力:)