Java 如何在OOP中实现图形层次结构

Java 如何在OOP中实现图形层次结构,java,oop,Java,Oop,我对一些基本OOP概念的理解有问题。我将试着用一个例子来描述它。假设我有一个应用程序,它可以绘制不同形状的图形 我创建了一个Figure类并添加了一个字段Shape(这是一种枚举,可以是Shape.Circle或Shape.Square) 当我需要向应用程序添加更多形状时,我必须向draw()方法添加更多ifs。我觉得很糟糕 我可以使Figure类抽象(或使其成为接口),从该类继承具体形状的图形并重写draw()方法 当我需要新的形状时,我只需要添加新的类 接下来,我决定我的数字要有一种颜色:黑

我对一些基本OOP概念的理解有问题。我将试着用一个例子来描述它。假设我有一个应用程序,它可以绘制不同形状的图形

我创建了一个Figure类并添加了一个字段Shape(这是一种枚举,可以是Shape.Circle或Shape.Square)

当我需要向应用程序添加更多形状时,我必须向draw()方法添加更多ifs。我觉得很糟糕

我可以使Figure类抽象(或使其成为接口),从该类继承具体形状的图形并重写draw()方法

当我需要新的形状时,我只需要添加新的类

接下来,我决定我的数字要有一种颜色:黑色还是白色。黑色正方形和白色正方形的绘制方式应不同。问题看起来是一样的。我可以在Figure类中添加颜色字段,并在每个draw方法中处理ifs,或者创建诸如BlackCircle、BlackSquare、WhiteCircle、WhiteSquare之类的类

后来,如果我决定为Figure添加另一个属性(比如大小可以是小的、中的或大的),我必须创建2*2*3类,比如BigBlackCircle、SmallWhiteSquare等等。我不能在运行时更改图形的颜色或形状。我认为这不是正确的方法

为了理解这个问题,我发现我仍然可以为所有数字设置一个单独的类。然后我将颜色、形状、大小存储为字段,并添加负责绘图的DisplayManager类。我可以为不同的绘图算法使用不同的DisplayManager实现

public class Figure {
    public Shape shape;
    public Color color;
    public Size size;
    public DisplayManager display;

    public void draw() {
        display.draw(this);
    }
}

public class DisplayManager {
    public void draw( Figure figure ) {
        // drawing based on figure's shape, color and size
    }
}

但通过这种方式,我回到了步骤1中的问题:我必须在draw()方法中处理许多if。有人能解释一下这里的正确方法吗?我应该如何设计类以节省应用程序的灵活性?

与其声明
DisplayManager.draw(Figure)
,不如声明
Figure.draw(DisplayManager)
。为显示管理器实现一些方法,以便可以从图[drawPoint(),drawLine(),…]中使用


对于
Figure
的每个扩展,实现自己的
绘图(DisplayManager)
,它使用给定的
DisplayManager的特定实例

amit所说的,并且您可以在Square类的draw()方法中处理绘制黑色或白色正方形的不同方式,使用if语句或类的其他属性

例如,可以使用color属性和另一个枚举属性,枚举绘制正方形的不同方法,并在draw()方法中处理它

例如,使用“大小”元素来显示一个概念:

public abstract class Figure {
    public enum Size {
        SMALL(10), MEDIUM(20), LARGE(30);

        private int actualSize;

        private Size(int actualSize) {
            this.actualSize = actualSize;
        }

        public int getActualSize() {
            return actualSize;
        }
    }

    public int x,y;

    public Size size = Size.MEDIUM;

    public Color color = Color.BLACK;

    public abstract void draw(DisplayManager displayManager);
}

public class Square extends Figure {
    public enum Corners {
        SHARP, ROUNDED
    }

    public Corners corners = Corners.SHARP;

    @Override
    public void draw(DisplayManager displayManager) {
        int s = size.getActualSize();
        displayManager.setColor(color);

        switch (corners) {
        case SHARP:
            displayManager.drawBox(x-s, y-s, x+s, y+s);
            break;
        case ROUNDED:
            displayManager.drawRoundedBox(x-s, y-s, x+s, y+s);
            break;
        }
    }
}
(为节省空间而将属性公开,在适用的情况下将private与getter/setter一起使用,当然需要设置属性:)


在这里,枚举有两种工作方式——一种实际保存用于绘图的可用数据,另一种只是充当鉴别器。

谢谢。我在GoF的设计模式中发现了几乎相同的解决方案。
public class Figure {
    public Shape shape;
    public Color color;
    public Size size;
    public DisplayManager display;

    public void draw() {
        display.draw(this);
    }
}

public class DisplayManager {
    public void draw( Figure figure ) {
        // drawing based on figure's shape, color and size
    }
}
public abstract class Figure {
    public enum Size {
        SMALL(10), MEDIUM(20), LARGE(30);

        private int actualSize;

        private Size(int actualSize) {
            this.actualSize = actualSize;
        }

        public int getActualSize() {
            return actualSize;
        }
    }

    public int x,y;

    public Size size = Size.MEDIUM;

    public Color color = Color.BLACK;

    public abstract void draw(DisplayManager displayManager);
}

public class Square extends Figure {
    public enum Corners {
        SHARP, ROUNDED
    }

    public Corners corners = Corners.SHARP;

    @Override
    public void draw(DisplayManager displayManager) {
        int s = size.getActualSize();
        displayManager.setColor(color);

        switch (corners) {
        case SHARP:
            displayManager.drawBox(x-s, y-s, x+s, y+s);
            break;
        case ROUNDED:
            displayManager.drawRoundedBox(x-s, y-s, x+s, y+s);
            break;
        }
    }
}