如何在OOP中实现数字层次结构

时间:2012-02-05 14:04:06

标签: java oop

我对理解一些基本的OOP概念有疑问。我将尝试用一个例子来描述它。假设我有一个应用程序应该绘制不同形状的数字。

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

public class Figure {
    public Shape shape;

    public void draw() {
        if( shape == Shape.Square )
            // draw a square
        else if( shape == Shape.Circle )
            // draw a circle
    }
}

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

我可以使Figure类抽象(或使它成为一个接口),从这个类继承具体形状的数字并覆盖draw()方法。

public abstract Figure { void draw(); }

public class Circle extends Figure {
    @Override public void draw() {
        // draw a circle
    }
}

// same for Square

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

接下来我决定要为我的数字设置颜色:黑色或白色。黑色正方形和白色正方形应以不同方式绘制。问题看起来一样。我可以在Figure类中添加color field并在每个draw方法中处理ifs,或者创建类似BlackCircle,BlackSquare,WhiteCircle,WhiteSquare的类。

稍后如果我决定为图添加另一个属性(让我们说大小可以是小,中或大)我必须创建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()方法中处理很多ifs。谁能在这里解释正确的方法?我应该如何设计类以节省应用程序的灵活性?

2 个答案:

答案 0 :(得分:3)

声明DisplayManager.draw(Figure),而不是声明Figure.draw(DisplayManager)。实现DisplayManager一些方法,以便可以从Figure [drawPoint(),drawLine(),....]中使用

对于Figure的每个扩展,请实现自己的draw(DisplayManager),该DisplayManager使用给定{{1}}的特定实例

答案 1 :(得分:2)

你说的是什么,你可以使用if-statement或类的其他属性来处理在Square类的draw()方法中绘制黑色或白色方块的不同方法。

例如,你可以有color属性,另一个enum属性枚举绘制Square的不同方法,并在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;
        }
    }
}

(属性公开以节省空间,在适用的情况下使用私有的getter / setter,当然需要设置属性:))

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