Ed *_* S. 6 oop interface-design design-patterns
我最近开始创建一个图像编辑工具,以满足非常具体的需求.对于那些打算使用它的人来说,这同样适合我自己的娱乐.然而,我在早期遇到了一些建筑障碍.
与任何图像编辑器一样,用户将使用"工具"来绘制和操纵图像.我的第一次尝试包括一个简单的界面:
public interface IDrawingTool
{
void DrawEffect( Graphics g );
// other stuff
}
Run Code Online (Sandbox Code Playgroud)
这(我认为)会很好,干净,便于维护和扩展.只需添加接口对象并在运行时调用所选接口对象的DrawEffect方法即可.
这种方法的问题在于不同的绘图工具不能干净地粘附到单个界面上.例如,钢笔工具只需知道要绘制的点即可工作.然而,矩形需要点击第一个点,以及当前位置.多边形工具需要跟踪多次鼠标点击.
我无法想出一个实现这个的好方法.我现在能想到的最好的方法是涉及每个工具的switch语句和case,这意味着绘图逻辑将在Canvas类中,而不是由Tool类型对象封装.因为这是练习,我想以正确的方式做到这一点.在此先感谢您的帮助.
好的,经验法则:如果您switch在代码草图中看到一条语句,则表明您需要使用多态性。因此,在这种情况下,您希望能够进行各种操作,并且您发现自己想要一个switch,所以您应该思考“我怎样才能使用多态性来实现这个东西?”
现在,看一下命令模式,其中您的对象是动词而不是名词。每个命令实现一个doThis()方法;当您构造对象时,您就确定了命令将执行的操作。
public interface Command {
public void doThis(Graphics g); // I don't promise returning
// void is the best choice
// Would it be better to return a Graphics object?
}
public class DrawRectangle implements Command {
public DrawRectagle( Point topLeft, Point btmRight) { // ...
}
public void doThis(Graphics g){ // ...
}
}
Run Code Online (Sandbox Code Playgroud)
现在,考虑一下如果您想实现撤消,您会做什么?
好吧,让我们再扩展一下。使用此模式的目的是确保客户不需要了解太多,除非您正在进行原始构造。因此,对于这个例子,让我们考虑绘制一个矩形。当您选择矩形工具时,您将在按钮单击事件处理程序上有一些代码(顺便说一句,这都是伪代码)
cmdlist = [] // empty list
bool firstClick = true
Point tl = br = new Point(0,0)
onClick:
if firstClick:
get mouse position into tl
firstClick = false
else:
get mouse position into br
cmdlist.append(new DrawRectangle(tl, br))
firstClick = true
Run Code Online (Sandbox Code Playgroud)
现在,当您选择了矩形后,您可以将 DrawRectangle 对象添加到命令列表结构中。稍后,您会浏览该列表
for cmd in cmdlist:
cmd.doThis(Graphics g)
Run Code Online (Sandbox Code Playgroud)
这些事情就完成了。现在很明显,您可以通过向 Command 添加“undoThis”方法来实现撤消。当您创建命令时,您必须构建代码,以便对象知道如何撤消自身。那么撤消意味着仅将最后一个 Command 对象从列表中取出并执行其 undoThis 方法。