【问题标题】:Problems with instanceOf when creating new objects from other objects从其他对象创建新对象时 instanceOf 的问题
【发布时间】:2013-05-24 16:40:45
【问题描述】:

我有一个类负责从Shape 对象创建Formation 对象。形状正如其名,在画布上绘制的形状(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,如果不将形状向下转换为适当的类,我就无法调用任何这些方法,这会引发使用@987654330 的问题@运算符。

我是否应该将 Shape 和 Formation 合并到一个类中,我是否应该尝试实现一个访问者模式(如果是,在这种情况下将如何实现)或者还有其他我没有想到的东西?

【问题讨论】:

  • 我不明白你为什么不想向下投射?那不会解决问题吗?只需先进行 instanceof 测试以检查它是否是正确的实例类型。
  • 用一个通用的 Formation 类代替怎么样?当然,如果每个阵型根本不同,这可能行不通。
  • 向下转换是一种丑陋且难以扩展的解决方案。如果您不会获得太多形状并且不想支持未知形状,即访问者是有意义的。插件提供额外的一个。更有意义的是,类型特定的逻辑比您想要放入类中的逻辑要多得多,例如创建弹出菜单。也许您甚至可以考虑使用 FormationVisitor 而不是 FormationFactoryVisitor。然而另一种方法是在每个形状上都有一个 toFormation() 方法

标签: java if-statement factory instanceof downcast


【解决方案1】:

这完全取决于您希望Shapes 和Formations 的分离程度。正如您所提到的,最简单的解决方案是向Shape 接口添加一个Formation createFormation() 方法。

但如果您想将Shapes 和Formations 分开,您将不得不做一些更高级的事情。我建议不要使用访问者模式,因为它非常不灵活。

作为替代方案,考虑添加一个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 应该在哪里初始化。这是否符合您的需求取决于您的代码结构。

【讨论】:

  • 尽管我不介意寻找最干净的解决方案,但我想我会采用toFormation() 方法。 Ty 为你所做的一切努力:)
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 2015-03-12
  • 2015-03-31
相关资源
最近更新 更多