1

好的,最近我用 Java 编写了一个“绘画应用程序”。类似于 MS Windows Paint 的小程序,显然(根据一些评估我的源代码的人)我没有在我的应用程序中正确使用类。不幸的是,我不知道可能出了什么问题,但没有人愿意告诉我什么是不正确的。

我有使用继承思想的“正确”类:

PaintObject  
-ClosedObject  
--RectangleShape  
--OvalShape  
-OpenObject  
--PointShape  
--LineShape  

但我仍然不知道代码中可能有什么问题,什么可能导致认为类没有正确使用......

唯一(在我看来)可能是错误的事实是,我通过创建新对象进行绘制,例如:new RectagleObject(...)new OvalShape(...)不是创建一个字段objectToBeDrawn变量(可能是一种PaintObject类型),然后在调用该方法时为其分配适当的形状executeOperation(显然连同那个特定形状的绘图)

这是代码示例:

public void executeOperation(Graphics2D gr, int oper, boolean drawingMode){
    if(oper==1){
        new RectangleShape(startLocation, endLocation, borderColor, fillColor).draw(gr);
    }
    else if(oper==2){
        new OvalShape(startLocation, endLocation, borderColor, fillColor).draw(gr);
    }
    ....//more operations
}

任何人都知道一般编程习惯可能有什么问题(除非我的“猜测”是正确的? - 如果是,请确认我的疑问)。或者也许还有别的东西?(跳过部分,oper==1因为我知道这些值应该定义为常量)

非常感谢任何帮助,我自己学习,并且很难猜测专业程序是如何设计的(并遵循他们的模式),因为我的经验是“有限的”(实际上没有)。

4

4 回答 4

3

如果您正在绘制光栅图像,您是否需要跟踪用户正在绘制的内容?也许您的意思是PenTool,RectangleTool等对象?

现在,似乎您创建的对象会持续存在并被重绘以绘制特定的形状。您可以在适当的时候简单地让工具对象绘制Image一次(只是永远不要清除图形上下文)。选择工具后,只需将特定工具分配给某个activeTool字段。

class DrawingTool {
     public void draw(Graphics g) { }
}

class PenTool extends DrawingTool {
     public void draw(Graphics g) {
         // some drawing logic
     }
}

class RectangleTool extends DrawingTool {
     public void draw(Graphics g) {
         // some other drawing logic
     }
}

所以而不是

oper = 1;

你会写

activeTool = new PenTool(); // or activeTool = PenTool.GetInstance();

或类似的东西。现在,当您想绘制某些东西时,只需调用 draw 方法即可。正如我之前所说,你可以简单地通过传入一个Image你永远不会清除的来做到这一点:

class DrawingCanvas {
     Image image = createImage(GetWidth(), GetHeight());
     DrawingTool activeTool;

     // this is what gets invoked on every frame
     public void paint(Graphics g){
          g.drawImage(image, 0, 0, null);
     }
}

// when you need to draw something
// (not on every frame, but something new)
activeTool.draw(image.getGraphics());
于 2012-07-12T18:32:55.293 回答
3
if(oper==1){
    //...
}
else if(oper==2){
    //...
}

这是正确使用面向对象编程应该能够在 99% 的时间内避免的那种代码。调查为什么你需要一个oper整数。您可能可以修改一种模式以消除对它的需求。例如,如果您当前正在为工具栏中的每个按钮分配一个整数值,您可以改为让按钮处理程序将当前设置为OperationFactory生成与该按钮关联的类型的对象的处理程序。

于 2012-07-12T18:36:38.080 回答
1

您的每种类型(特别是 OvalShape 和 RectangleShape)都应该实现“executeOperation”方法。此方法应覆盖基类(封闭对象)中的“executeOperation”方法。

这将摆脱对 if(oper == 2)... else (oper == 2) 的需要。它只会调用与对象类型相关的实现。

于 2012-07-12T18:43:13.170 回答
0

从小片段中,您可能可以更多地使用多态性。就像有一个父抽象类/接口,它定义了 executeOperation(Graphics2D gr, boolean drawingMode) 方法,然后为您支持的每个操作扩展/实现它(也许也可以删除绘图模式,但我看不到它的作用。)可以也可能将 graphics2D 放入构造函数中。

于 2012-07-12T18:33:36.490 回答