- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在开发一个 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
模式介入了。每个工具将实现一个抽象工厂
,我们将为每种类型的Shape
提供操作实现。
总结
根据我的建议,这是领域模型草案:
为了从我的建议中得到完整的想法,我还发布了特定用例的序列图:
使用 ToolUI
,用户点击 ShapeUI
的 ControlPointUI
关于java - 在绘图应用程序中分离模型和 View / Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30155807/
我在尝试使用 jpa2.0 将包含持久实体和分离实体(新创建的实体)的实体列表更新到我的数据库中时遇到错误。 我的实体包含在合并数据时出现错误(在标题中提到)的内部实体: Class supercla
我在分层 Pane 中有一组面板。我需要一个分隔符来将 sideBar 与 topBar 和 tabbedPanel 分开。我留了一个 10 像素的缓冲区来放置它。不幸的是,可能由于它是 JLayer
在我从数据库中读取的代码中,我还使用自定义适配器打印出每一行,该行中有一个 texttview、2 个按钮和一个 edittext。这一切都很好,但是当按下按钮时,edittext 会递增或递减,有没
我有一个由 Hibernate 4.3.4 管理的实体,它有一个其他实体的一对多集合。 在我的处理过程中,我必须分离父实体(将分离级联到子列表)。但是,当我向列表中添加一个尚未持久化的新项目并执行分离
我想追加一行,该行应该是表格的最后一行。在我的代码中,它似乎在第一次动态添加行时起作用。但是当添加其他行时它不会成为最后一行。 我总是希望“subtot”行成为最后一行,但是当我追加其他行时,它不
我试图用它们之间的空格分隔这 2 个 div(请参见图 1)。问题是当我添加边距或填充时会发生这种情况(请参见图 2)。 这是我的代码,请注意我没有使用 Bootstrap: .row { mar
我的服务器包含一些 ServerActor。该 actor 接收 RegisterClient 消息并将 ActorRefs 添加到已注册客户端列表中。 我还有多个客户端,每个客户端都包含 Clien
假设我有一个需要两个参数的函数,并且参数的顺序会影响结果。 是否可以将第一个参数传递给 partial 或 comp 函数,然后将另一个参数传递给它,如下所示: (defn bar [arg1 arg
如何搜索和分离多个后代键。 例子: (def d {:foo 123 :bar { :baz 456 :bam { :w
我正在尝试为 Slick 表创建一个类型安全的动态 DSL,但不确定如何实现这一点。 用户可以通过以 form/json 格式发送过滤器来将过滤器发布到服务器,我需要使用所有这些来构建一个 Slick
我是新来的,我发现看到充满大量函数和变量初始化以及 UI 的组件时眼睛很痛。是否可以将它们分开? 而不是默认设置,如下所示。如何将业务逻辑分离到另一个文件中? function MyComponent
我试图通过将参数粘贴在一起来使用分离。这应该是一件容易的工作,但不适合我。当我想到使用 eval(parse()) 时,我知道是时候寻求帮助了 通常,如果我加载一个包,我可以按如下方式分离它: det
(dissoc :a m)允许我解除给定的键。但是,有没有办法使用谓词函数来分离 pred 为真的任何键? (dissoc-with-pred pred? m) 所以给了一张 map - {:a 2
我编写了一个使用 devtools 来包含内部数据的包: devtools::use_data(.data, internal = T, overwrite = T) 我最近更改了该数据并重建了包。我
所以我有一个脚本,我想在我的服务器上运行它而不会打扰我。所以我想我会在 tmux 窗口中运行服务器,然后 detach这样我就可以简单地 attach如果我想查看进度(此脚本需要数天才能运行)。 但是
ThreeJS中动画数据和模型数据是否可以解耦? 这样就可以交换模型并保留动画?我认为这可能非常强大 我知道如何在 ThreeJS 中做到这一点的方法是将每个动画一个接一个地打包在一个模型中,这似乎是
我有一堆(Ruby)脚本存储在服务器上。到目前为止,我的团队通过打开一个启动脚本名称列表的访问器应用程序来使用它们,然后他们在工作文件夹中的文件上选择要在该实例中运行的脚本。脚本直接从服务器运行,因此
我想知道 javascript 如何包含在 jsp 中 - 我们是否可以在 .js 文件中放置 jsp 能够识别的任何代码,而不仅仅是 javascript 代码? 我有一些常见的 JavaScrip
您是否可以在 Dockerfile 中指定一个选项,默认使用它构建的容器以分离方式运行。 这将导致与 -d 相同的结果: docker run -d 这样 docker run 默认情况下会分离运
我正在为现有的 Java 程序开发 Java 插件。现有程序使用特定版本的 eclipse.uml2.*,我的插件也是如此。不幸的是,我的插件需要更新版本。 为了运行该插件,我需要将其导出到 Jar
我是一名优秀的程序员,十分优秀!