我对理解一些基本的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。谁能在这里解释正确的方法?我应该如何设计类以节省应用程序的灵活性?
答案 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,当然需要设置属性:))
在这里,枚举有两种方式 - 一种实际上可以保存用于绘图的可用数据,另一种只是作为鉴别器。