我正在使用 vector 绘图应用程序(在Java中),并且在模型类与 View / Controller 类之间的分离方面处于挣扎中。
一些背景:
您可以绘制不同的形状:
矩形,直线和扇形段
有4种工具可以操纵 Canvas 上的形状:
缩放工具,移动工具,旋转工具和变形工具
对于这个问题,变形工具是最有趣的一个:
它使您可以通过拖动形状的一个点并调整其他属性来更改形状,如下图所示:
这些转换规则对于每种形状都是不同的,我认为它们是模型业务逻辑的一部分,但从某种意义上讲,它们需要公开给 View / Controller (工具类),以便可以应用正确的规则。
此外,形状通过不同的值在内部表示:
-矩形存储为中心,宽度,高度,旋转
-线被存储为起点和终点
-扇形段存储为中心,半径,角度1,角度2
我计划在将来添加更多形状,例如星星,气泡或箭头,每个形状都有自己的控制点。
我还计划在将来添加更多工具,例如旋转或缩放形状组。
每个工具的控制点都不同。例如,使用缩放工具时,您无法捕获中心点,但是每个缩放控制点都需要与一个枢轴点(或多个枢轴点)相关联,以便用户选择。
对于简单的形状(如矩形,直线和扇形),该类的每个实例的控制点都相同,但 future 形状(如贝塞尔曲线或星形(具有可配置的峰值数))每个实例将具有不同数量的控制点。
那么问题是,有什么方法可以很好地建模和实现这些控制点?
由于每种工具的工具略有不同,并带有一些工具/ Controller 特定的数据,因此它们以某种方式属于工具/ Controller 。但是,由于它们也针对每种形状,并且具有非常重要的域逻辑,因此它们也属于模型。
我想避免在每次添加一个工具或形状时为每种工具/形状组合添加一种特殊类型的控制点的组合爆炸。
更新:再举一个例子:将来可能会出现一个我想支持的新形状的想法:圆弧。它与饼图段相似,但是看起来有些不同,并且在拖动控制点时的行为完全不同。
为了实现这一点,我希望能够创建一个实现我的Shape接口(interface)的ArcShape类并完成它。
最佳答案
基本注意事项
首先,让我们为简单起见进行一些定义。Entity
是域模型对象,它定义了所有的结构和行为,即逻辑。EntityUI
是表示UI中Entity
的图形控件。
因此,基本上,对于Shape
类,我认为ShapeUI
必须非常了解Shape
的结构。该结构主要由我猜想的控制点组成。换句话说,有了关于控制点的所有信息(将来可能是 vector ),ShapeUI
将能够在UI上绘制自己。
初步建议
我对Shape
类的建议是,Shape
类定义了所有行为。 ShapeUI
类将了解Shape
类,并保留对其表示的引用,通过它可以访问控制点,并能够操纵它们,例如,控制点。设置他们的位置。 Observer
模式只是要求在此上下文中使用。特别地,Shape
类可以实现Observable
,并且ShapeUI
将实现Observer
并订阅相应的Shape
对象。
所以基本上在这种情况下会发生什么,ShapeUI
对象将处理所有UI操作,并负责更新Shape
参数,例如控制点位置。然后,一旦位置更新发生,Shape
对象就会在状态更改时执行其逻辑,然后盲目地(不知道ShapeUI
)将更新后的状态通知给ShapeUI
。因此,ShapeUI
相应地将绘制新状态。在这里,您将获得低耦合模型和 View 。
至于Tools
,我个人的观点是每个Tool
必须知道如何操作每种类型的Shape
,即每个形状操作逻辑必须在Tool
类内部实现。对于 View 和模型的解耦,与Shape
几乎相同。 ToolUI
类处理光标的单击位置,单击的ShapeUI
,单击的控制点等。通过获取此信息,ToolUI
将其传递给适当的Tool
对象,然后该对象将基于接收的参数。
处理不同的形状类型
现在,当谈到以自己的方式处理不同的Tool
的Shape
时,我认为Abstract Factory
模式介入了。每个工具都将实现一个Abstract Factory
,在此我们将为每种类型的Shape
提供操纵实现。
摘要
根据我的建议,这是领域模型(Domain Model)草案:
为了从我的建议中得到整个想法,我还发布了特定用例的序列图:
用户使用ToolUI
单击ShapeUI
的ControlPointUI
关于java - 在绘图应用程序中分离模型和 View / Controller ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30155807/